IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Problème lors de l'envoi d'une matrice par socket


Sujet :

C

  1. #1
    Futur Membre du Club Avatar de Blackbelt_29
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2016
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2016
    Messages : 19
    Points : 9
    Points
    9
    Par défaut Problème lors de l'envoi d'une matrice par socket
    Bonjour,

    J'essaye d'envoyer une matrice de float (tableau à deux dimensions) par socket, avec les cours sur internet j'arrive bien à envoyer d'un client vers un serveur une chaine de caractère ainsi que des structures. Du coup mon idée était justement d'utiliser des structures afin d'envoyer mon tableau à deux dimensions. Du coup je crée un tableau 2*2 que je copie dans ma structure et je l'envoie. Le problème est que quand j'essaye de la récupérer j'ai une erreur de segmentation, et je ne vois absolument pas d'où ça peut venir ?


    Voici le code en question du côté serveur:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    //Création de la structure
        typedef struct Image Image;
    struct Image{
        float** tabImage;
    };
     
        float **tab2=NULL;
    tab2=allocation(2,2);
    tab2[0][0]=2.0;
    tab2[0][1]=4.32;
        tab2[1][0]=1.47;
        tab2[1][1]=8.37;
     
    Image NewImage;
    NewImage.tabImage=allocation(2,2);//Fonction qui alloue dynamiquement la matrice
    int i,j;
     
         //Recopie les valeurs de tab2 dans la structure
     
         for(i=0;i<2;i++)
        for(j=0;j<2;j++)
            NewImage.tabImage[i][j]=tab2[i][j];
     
         //Envoie la structure
     sock_err = send(csock,&NewImage,sizeof(NewImage), 0);


    Et voici le code en question côté client
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    /*Déclaration de la structure coté client
    typedef struct Image Image;
        struct Image{
            float** tabImage;
        };
     
        Image NewImage;
        NewImage.tabImage=allocation(2,2); //allocation  dynamique du tableau
        recv(sock,&NewImage.tabImage ,sizeof(NewImage), 0);
    //Reception de la structure
    Je n'ai pas mis le reste de la fonction car je pense que l'erreur vient de ces lignes (car ça marche bien sinon avec une chaine de caractère ou une structure avec des int, double...),mais si il faut je la mettrai sans problème !

    Merci !

  2. #2
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Il y a deux incompréhensions ici :

    • lorsque tu passes ta structure à send, ce ne sont pas les données de la matrice qui sont transmises mais le contenu du pointeur vers le bloc mémoire où se trouve cette matrice. Ce bloc est alloué séparément, il ne fait pas partie de ta structure qui en a simplement connaissance.
    • sizeof est un opérateur statique, tu ne peux pas l'utiliser pour récupérer la taille d'un bloc mémoire déterminée à l'exécution. sizeof(<variable de type struct Image>) retournera toujours la même valeur n'importe où dans le programme (à savoir ici sizeof(float **)), que la matrice pointée fasse 2x2 ou 16045x1454013.

  3. #3
    Futur Membre du Club Avatar de Blackbelt_29
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2016
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2016
    Messages : 19
    Points : 9
    Points
    9
    Par défaut
    Merci pour ta réponse


  4. #4
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    • Que crois-tu qu'il se passe en mémoire lorsque tu crées ta structure et que tu alloues dynamiquement de la place pour ses membres ?
    • Ce que send attend, c'est une adresse mémoire et le nombre d'octets à lire à partir de cette adresse. Que crois-tu qu'il se passe lorsque tu lui donnes l'adresse d'une variable de type struct Image et la taille d'une struct Image ?

    Ce sont de vraies questions, je voudrais savoir ce que tu as déjà assimilé du fonctionnement.


    Citation Envoyé par Blackbelt_29 Voir le message
    Ça c'est correct mais plus généralement, la taille du bloc alloué a été calculée par ta fonction allocation, c'est l'argument de malloc.

    Citation Envoyé par Blackbelt_29 Voir le message
    , ou bien
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    4*sizeof(NewImage.TabImage)
    Ça c'est incorrect. Quelle est la différence entre sizeof(NewImage.TabImage) et sizeof(float) selon toi ?

  5. #5
    Futur Membre du Club Avatar de Blackbelt_29
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2016
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2016
    Messages : 19
    Points : 9
    Points
    9
    Par défaut
    Merci pour ta réponse ! J'ai regardé de nouveau le cours et voila ce que j'ai compris :

    Que crois-tu qu'il se passe en mémoire lorsque tu crées ta structure et que tu alloues dynamiquement de la place pour ses membres ?
    À ce moment-là le programme va réserver des places dans la mémoire (un nombre d'adresses égal à la dimension de ma matrice) du coup je vais réserver dans la mémoire de l'ordinateur 4 adresses de celle-ci, qui pour l'instant ne contiennent aucune valeur !

    Ce que send attend, c'est une adresse mémoire et le nombre d'octets à lire à partir de cette adresse. Que crois-tu qu'il se passe lorsque tu lui donnes l'adresse d'une variable de type struct Image et la taille d'une struct Image ?
    Justement c'est peu être là où je n'ai pas trop compris , pour moi lorsque je fais &NewImage TabImage je ne donne pas à send l'adresse de la variable, mais la valeur contenue à l'adresse de cette adresse. Du coup j'envoie les valeurs contenues dans les adresses que je venais d'allouer dynamiquement .

    En gros quand je fais &NewImage TabImage pour moi il va chercher la valeur à cette adresse et l'envoyer (ici il enverra 32) :
    Adresse Valeur
    0xFFFFFF 32


    Ça c'est incorrect. Quelle est la différence entre sizeof(NewImage.TabImage) et sizeof(float) selon toi ?
    Pour moi sizeof(float) correspond à la taille prise en mémoire d'un flottant et sizeof(NewImage.TabImage) correspond lui à la taille d'un tableau non alloué donc pas grand chose

    Edit : Du coup si je corrige le code par cette ligne est-ce correct ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sock_err = send(csock,*NewImage.tabImage,4*sizeof(float), 0);

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Ce ne sera pas suffisant, parce que NewImage.TabImage est un tableau de pointeurs.
    Si cette matrice a été allouée intelligemment, alors un send(csock, &(NewImage.tabImage[0][0]), 2*2*sizeof(float), 0) pourrait suffire. Mais dans le cas d'un tableau de tableaux (ce qui est hélas le cas le plus fréquent chez ceux qui débutent en C), même ça ne suffira pas, et tu devras faire une boucle de send() qui envoie séparément chaque ligne de ta matrice.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Futur Membre du Club Avatar de Blackbelt_29
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2016
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2016
    Messages : 19
    Points : 9
    Points
    9
    Par défaut
    Du coup est-ce possible de faire ça :

    Ma structure créée un tableau de pointeur, du coup chaque case du tableau de pointeur attend une adresse (c'est la définition d'un pointeur).
    Dans la boucle for je lui donne donc l'adresse de la valeur de chaque élément que je veux.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
      for(i=0;i<2;i++)
        for(j=0;j<2;j++)
            NewImage.tabImage[i][j]=&tab2[i][j];
    Ensuite pour vérifier il suffit juste de faire un printf, ce qui est censé m'afficher la valeur de l'adresse pointée.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf("%.2f\n",*NewImage.tabImage[0][0]);
    et si j'écris mon send de la façon suivante cela peut-il suffire ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    send(csock, *NewImage.tabImage, 2*2*sizeof(float), 0)
    Je vais tester ça et si ça ne marche pas je vais tester ta technique Médinoc pour allouer un tableau 2D !

    Merci en tout cas pour ta réponse

    /*-------------*/

    EDIT : Je viens de tester ta solution Médinoc (avec une allocation de tableau 2D) et cela fonctionne bien pour des petites matrices 3*3, 10*10...
    Cependant mon but ultime est d'envoyer une matrice 512*512 (la taille d'une image), j'alloue donc le tableau 2D de 512*512, et lorsque je l'envoie les valeurs sont bien envoyés jusqu'à une certaine valeur (la position y=21 et x =192), serais-tu pourquoi toutes les valeurs ne sont pas envoyées ?

  8. #8
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Citation Envoyé par Blackbelt_29 Voir le message
    Du coup est-ce possible de faire ça :

    Ma structure créée un tableau de pointeur, du coup chaque case du tableau de pointeur attend une adresse (c'est la définition d'un pointeur).
    Dans la boucle for je lui donne donc l'adresse de la valeur de chaque élément que je veux.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
      for(i=0;i<2;i++)
        for(j=0;j<2;j++)
            NewImage.tabImage[i][j]=&tab2[i][j];
    Ensuite pour vérifier il suffit juste de faire un printf, ce qui est censé m'afficher la valeur de l'adresse pointée.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf("%.2f\n",*NewImage.tabImage[0][0]);
    et si j'écris mon send de la façon suivante cela peut-il suffire ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    send(csock, *NewImage.tabImage, 2*2*sizeof(float), 0)
    Attends, c'est carrément une matrice de pointeurs? Un tableau de tableaux de pointeurs?
    (voire un tableau de tableaux de tableaux?)
    Dans ce cas, il n'y a absolument pas moyen que ça marche avec un seul send(). send() ne peut transmettre que des données sur un tableau continu, et ne peux pas transmettre de pointeurs (enfin il peut envoyer leur valeur, mais l'adresse n'aurait aucun sens dans le processus de destination)
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  9. #9
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    send attend une séquence continue (double emphase, c'est important) d'octets, à partir d'une adresse de départ. Or ce qui coince c'est que la disposition en mémoire des informations que tu veux transmettre ne l'est pas: les informations sont éparpillées au sein du tas, et comme je ne pense pas que tu aies alloué ta matrice comme Médinoc le propose il y a même une indirection supplémentaire.

    Ta structure occupe un bloc en mémoire. La liste de colonnes de ta matrice en occupe un autre, et la liste d'éléments de chaque colonne un autre à son tour. Tes informations sont réparties sur autant de blocs que tu as fait d'appels à malloc. À savoir 1 + 1 + le nombre de colonnes (moins un si ta structure est allouée sur la pile).

    Afin de transmettre tes informations, tu as donc deux approches à ta disposition :

    • effectuer autant d'appels à send qu'il y a de blocs non contigüs à traiter (c'est en général préférable s'il y a beaucoup de données à transmettre) ;
    • rassembler toutes les données à un seul endroit en mémoire en les copiant dans un buffer temporaire et faire un seul appel à send.

  10. #10
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Citation Envoyé par Blackbelt_29 Voir le message
    EDIT : Je viens de tester ta solution Médinoc (avec une allocation de tableau 2D) et cela fonctionne bien pour des petites matrices 3*3, 10*10...
    Cependant mon but ultime est d'envoyer une matrice 512*512 (la taille d'une image), j'alloue donc le tableau 2D de 512*512, et lorsque je l'envoie les valeurs sont bien envoyés jusqu'à une certaine valeur (la position y=21 et x =192), serais-tu pourquoi toutes les valeurs ne sont pas envoyées ?
    Un problème de taille de buffer interne par exemple (surtout si tu es en asynchrone). Vérifie les valeurs retournées par send() et recv(), appelant recv() en boucle tant qu'elle ne retourne pas une valeur négative ou nulle...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  11. #11
    Futur Membre du Club Avatar de Blackbelt_29
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2016
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2016
    Messages : 19
    Points : 9
    Points
    9
    Par défaut
    rassembler toutes les données à un seul endroit en mémoire en les copiant dans un buffer temporaire et faire un seul appel à send.
    c'est ce que j'essaye de faire depuis le début et je pense que c'est ma façon de penser qui est mauvaise sur le coup.

    1.Tout d'abord je crée ma structure (c'est un tableau de pointeur) et j'alloue la mémoire en me basant sur le procédé du tableau 2D de Médinoc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    typedef struct Image Image;
    	struct Image{
    	    float **tabImage;
    	};
    2.j'ai un tableau de pointeur 'tab2' qui contient les valeurs que je veux envoyer. Je recopie donc les valeurs de ce tableau dans ma structure.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
              for(i=0;i<512;i++)
    		  for(j=0;j<512;j++)
    		     NewImage.tabImage[i][j]=tab2[i][j];
    En testant avec printf("%.2f\n",NewImage.tabImage[y][x]); j'ai bien les valeurs qui sont recopiées dans ma structure, je l'envoie donc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sock_err = send(csock, &(NewImage.tabImage[0][0]), 512*512*sizeof(float), 0);
    3.À la réception je crée la même structure que j'alloue de la même façon et j'utilise recv() pour reprendre mes données ;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     recv(sock, &(NewImage.tabImage[0][0]) ,512*512*sizeof(float), 0);
    Et c'est justement en procédant de cette façon que j'arrive à envoyer uniquement une partie de l'information et s'arrête en plein milieu du tableau !

    Du coup j'ai essayé d'appeler recv() en boucle mais j'ai toujours le même souci.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    do{
        int retVal = recv(sock, chaine, sizeof(chaine) - 1, 0)!= SOCKET_ERROR;
        }while(retVal < 0);
        /*Je reste dans ma boucle tant qu'il y a des octets à envoyer */
    ma question : est-ce qu'il y a une erreur dans ma façon de penser ? est-ce qu'il faut que j'envoie de la même manière la fonction send ?

    effectuer autant d'appels à send qu'il y a de blocs non contigüs à traiter (c'est en général préférable s'il y a beaucoup de données à transmettre) ;
    C'est une bonne idée effectivement, mais comment procède t-on ? Avec un for (exemple : (for i=0;i<nombre_de_ligne;i++) on envoie la ligne) et on procède de même à la réception ?

    EDIT:
    • Je viens aussi tester en envoyant non plus une matrice N*M, mais un vecteur contenant toutes les lignes à la suite (plus facile que d'envoyer une matrice) et j'ai exactement le même problème, j'envoie une partie et à partie d'un certain moment il n'envoie plus rien ! Du coup je pense effectivement que c'est un problème de taille de buffer, mais comment fait-on pour l'augmenter je vois pas comment je pourrais faire ?


    Merci de votre aide

  12. #12
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Citation Envoyé par Blackbelt_29 Voir le message
    Et c'est justement en procédant de cette façon que j'arrive à envoyer uniquement une partie de l'information et s'arrête en plein milieu du tableau !
    C'est-à-dire ? Comment le constates-tu ? recv ne te renvoie pas 1 MiB ou ce sont les données qui sont corrompues ?

    Peux-tu également nous montrer le code d'allocation des structures et des buffers ?

  13. #13
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Citation Envoyé par Blackbelt_29 Voir le message
    Du coup j'ai essayé d'appeler recv() en boucle mais j'ai toujours le même souci.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    do{
        int retVal = recv(sock, chaine, sizeof(chaine) - 1, 0)!= SOCKET_ERROR;
        }while(retVal < 0);
        /*Je reste dans ma boucle tant qu'il y a des octets à envoyer */
    ma question : est-ce qu'il y a une erreur dans ma façon de penser ? est-ce qu'il faut que j'envoie de la même manière la fonction send ?
    Tu oublies de tenir compte de l'avancement! Il te faut un truc du genre:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    int tailleARecevoir = ...
    int offset = 0;
    int retVal;
    do
    {
    	retVal = recv(sock, monBuffer+offset, sizeof(monBuffer)-offset, 0); //Note: monBuffer a intérêt à être un tableau et non un pointeur, pour que ceci marche
    	if(retVal > 0)
    		offset += retVal;
    } while(retVal > 0 && offset < tailleARecevoir);
    //Traitement de refVal après la fin de la boucle
    if(retVal > 0)
    {
    	//Succès! Maintenant, on a offset >= tailleARecevoir (et idéalement, c'est égal).
    }
    else if(retVal == SOCKET_ERROR)
    {
    	//Grosse erreur
    }
    else if(retVal == 0)
    {
    	//Déconnexion
    }
    else
    {
    	//Pas censé arriver!
    }
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  14. #14
    Futur Membre du Club Avatar de Blackbelt_29
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2016
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2016
    Messages : 19
    Points : 9
    Points
    9
    Par défaut
    Citation Envoyé par Matt_Houston Voir le message
    C'est-à-dire ? Comment le constates-tu ? Peux-tu également nous montrer le code d'allocation des structures et des buffers ?
    Sachant que je connais les valeurs de mon tableau je regarde si j'ai les mêmes à l'arrivée, et justement à partir d'un moment je passe d'une valeur à '0.00' et pour toutes les valeurs suivantes j'ai la même chose !

    Le code pour l'allocation des structures et des buffers

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    /*------------------------------------------------------*/
    /*      Allocation mémoire pour le tableau 2D qui       */
    /*      contiendra l'image  à la position n             */
    /*------------------------------------------------------*/
    float ** allocation(int height,int width)
    {
        float ** ppValeurs=NULL;
        int taille1x2 = height*width;
        if(taille1x2 / width != height)
            return NULL; /*Débordement des tailles*/
     
        ppValeurs = malloc(sizeof(*ppValeurs)*height);
        if(ppValeurs != NULL)
        {
            float * pValeurs = malloc(sizeof(*pValeurs)*taille1x2);
            if(pValeurs != NULL)
            {
                int i;
                /* Affecter tous les pointeurs */
                for(i=0 ; i<height ; ++i)
                    ppValeurs[i] = pValeurs + (i*width);
            }
            else
            {
                /* Echec de la seconde allocation, liberer la premiere */
                free(ppValeurs), ppValeurs=NULL;
            }
        }
        return ppValeurs;
    }

    Citation Envoyé par Médinoc Voir le message
    Tu oublies de tenir compte de l'avancement!
    Je vais voir si ça fonction en me basant sur ça ! Et du coup je ne touche pas au send ?

  15. #15
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Si le send() fait tout d'un coup et que le send() n'est pas en mode non-bloquant, tu ne devrais pas avoir à toucher au send().
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  16. #16
    Futur Membre du Club Avatar de Blackbelt_29
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2016
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2016
    Messages : 19
    Points : 9
    Points
    9
    Par défaut
    En me basant sur ce que tu propose j'ai fais ça, mais j'ai le même soucis ou j'ai plus rien à partir d'une certaine position

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    	typedef struct Image Image;
    	struct Image{
    	    float tabImage[512][512];
    	};
    	float **tab2=NULL;
    	Image NewImage;	
    	//NewImage.tabImage=allocation(512,512);
    	tab2=allocation(512,512);
     
    	int tailleARecevoir = 512*512;
    	int offset = 0;
    	int retVal;
     
    	do
    	{
    	retVal = recv(sock,&(NewImage.tabImage)+offset, sizeof(NewImage)-offset, 0);
    	if(retVal > 0)
    		offset += retVal;
    	} while(retVal > 0 && offset < tailleARecevoir);
    	if(retVal > 0){
    		printf("Matrice recu\n");
            }
    	else if(retVal == SOCKET_ERROR){
    		printf("erreur lors de l'envoi\n");
    	}
    	else if(retVal == 0){
    	        closesocket(sock);
    	}
    	else{
    		printf("Pas censé arriver!\n");
    	}
    Même soucie si j'alloue de façon dynamique

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    	typedef struct Image Image;
    	struct Image{
    	    float **tabImage;
    	};
    	float **tab2=NULL;
    	Image NewImage;	
    	NewImage.tabImage=allocation(512,512);
    	tab2=allocation(512,512);
     
    	int tailleARecevoir = 512*512;
    	int offset = 0;
    	int retVal;
     
    	do
    	{
    	retVal = recv(sock,&(NewImage.tabImage[0][0])+offset, 512*512*sizeof(float)-offset, 0);
    	if(retVal > 0)
    		offset += retVal;
    	} while(retVal > 0 && offset < tailleARecevoir);
    	if(retVal > 0){
    		printf("Matrice recu\n");
            }
    	else if(retVal == SOCKET_ERROR){
    		printf("erreur lors de l'envoi\n");
    	}
    	else if(retVal == 0){
    	        closesocket(sock);
    	}
    	else{
    		printf("Pas censé arriver!\n");
    	}
    Du coup soit j'ai mal effectué le do/while, soit c'est dans le send où le problème se trouve (l'envoi du buffer ne se fait pas en entier ) ?

  17. #17
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Il y a un conflit ici au niveau de tailleARecevoir, entre taille en octets et taille en floats.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  18. #18
    Futur Membre du Club Avatar de Blackbelt_29
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2016
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2016
    Messages : 19
    Points : 9
    Points
    9
    Par défaut
    Après un week end passé à essayer de trouver la solution que je n'ai toujours pas réussi à trouver je me permets de revenir vers vous !

    J'ai changé mon algorithme pour non plus envoyer une matrice cette fois-ci mais un vecteur de taille longueur*largeur qui je pense me paraît plus simple à envoyer et à allouer en mémoire !

    Après avoir changé mon code et l'avoir compilé voici ce qu'il me donne :
    erreur lors de l'envoi
    *** stack smashing detected ***: ./client terminated
    Du coup je pense que mon erreur vient de la fonction présente dans le serveur et peut-être pas au niveau de la réception comme je le pensais ?

    Merci pour vos réponses !

    Voici mon code serveur pour l'envoi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    	typedef struct Image Image;
    	struct Image{
    	    float *tabImage;
    	};
     
            ENVOI DE L'IMAGE	*/
    		Image NewImage;	
    		NewImage.tabImage=NULL;
    		NewImage.tabImage=malloc(512*512*sizeof(float));		
    		int i;
    		for(i=0;i<512*512;i++){
    			NewImage.tabImage[i]=imageVect[i];
    		}
    		printf("%.2f\n",NewImage.tabImage[22*512+193]);//je vérifie si la copie se fait bien ce qui est le cas 
     
    	        sock_err = send(csock, &(NewImage.tabImage[0]), 512*512*sizeof(float), 0);
     
    		//dellocation(NewImage.tabImage);
    		dellocation(tab2);
                   	/*	FIN ENVOI DE L'IMAGE	*/
    Mon code client pour la reception :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
     /* ----------------------------------------------------------------- */
    	/*			Reception de la structure 	             */
     
    	typedef struct Image Image;
    	struct Image{
    	    float *tabImage;
    	};
    	Image NewImage;	
            NewImage.tabImage=NULL;
    	NewImage.tabImage=malloc(512*512*sizeof(float));	
     
    	long int tailleARecevoir = 512*512*sizeof(float);
    	printf("taille a recevoir = %ld\n",tailleARecevoir);
    	int offset = 0;
    	int retVal;
     
    	do
    	{
    	retVal = recv(sock,&(NewImage.tabImage[0])+offset, 512*512*sizeof(float)-offset, 0);
    	if(retVal > 0)
    		offset += retVal;
    	} while(retVal > 0 && offset < tailleARecevoir);
    	if(retVal > 0){
    		printf("Matrice recu\n");
            }
    	else if(retVal == SOCKET_ERROR){
    		printf("erreur lors de l'envoi\n");
    	}
    	else if(retVal == 0){
    	        closesocket(sock);
    	}
    	else{
    		printf("Pas censé arriver!\n");
    	}
     
    	free(NewImage.tabImage);
            /* On ferme la socket */
            closesocket(sock);
     
            #if defined (WIN32)
                WSACleanup();
            #endif
            } 
        }

  19. #19
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Attention, ajouter un offset à un pointeur ajoute l'offset multiplié par la taille de la donnée pointée.
    Personnellement je passe par une fonction intermédiaire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void* OffsetInBytes(void* pv, ptrdiff_t offset)
    {
    	char *pBytes = pv;
    	pBytes += offset;
    	return pBytes;
    }
    void const* OffsetInBytesC(void const* pv, ptrdiff_t offset)
    {
    	char const *pBytes = pv;
    	pBytes += offset;
    	return pBytes;
    }
    Ou sinon, je considère directement mon buffer comme un tableau de bytes.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  20. #20
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Citation Envoyé par Blackbelt_29 Voir le message
    J'ai changé mon algorithme pour non plus envoyer une matrice cette fois-ci mais un vecteur de taille longueur*largeur qui je pense me paraît plus simple à envoyer et à allouer en mémoire !
    Je ne vais pas pérorer que j'te l'avais bien dit voici quelques semaines mais bon..


    Pas mieux que Médinoc, ((char *)&NewImage.tabImage[0]) + offset.

    D'une manière générale pense à préciser où ça plante (dans le serveur / client ? dans quelle section à peu près ?). Si le crash est reproductible tu as plusieurs méthodes à ta disposition pour le localiser : gdb, le spam de fprintf(stderr, ...), valgrind...

Discussions similaires

  1. Problème lors de l'envoi d'une newsletter
    Par ghir_ana dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 06/07/2011, 23h51
  2. [AJAX] Envoie d'une requête AJAX
    Par tidus_6_9_2 dans le forum AJAX
    Réponses: 16
    Dernier message: 14/04/2010, 15h23
  3. Envoi d'une matrice sur socket UDP
    Par caubios dans le forum Qt
    Réponses: 0
    Dernier message: 10/02/2010, 19h10
  4. Réponses: 4
    Dernier message: 04/02/2010, 14h44
  5. Réponses: 9
    Dernier message: 15/03/2007, 16h17

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo