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 :

Socket C/Java sous linux


Sujet :

C

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Août 2010
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 7
    Par défaut Socket C/Java sous linux
    Bonjour à tous,

    Cela fait pas mal de jours que j'essaye de résoudre un problème (qui doit être tout bête mais dont je ne trouve pas la solution...). Quand je dis jours, j'ai vraiment mis ce temps là dont plusieurs nuits blanches ! Donc je commence à désespérer.

    Je vais vous exposez mon problème aussi clairement que possible. Le sujet étant assez complexe, si je ne suis pas assez clair sur certains points, n"hésitez pas à me demander !

    J'essaye de d'échanger des données à travers des sockets TCP en C et Java. Mon serveur est codé en C et le client en Java. Pour cela, je n'échange que des byte(java) et char(C) sur la socket. Pour structurer ces échanges et pour pouvoir ranger les données reçues/envoyées, j'utilise deux structures principales. A chaque transmission, je parcours ces structures et j'envoie/reçois octet par octet les données à travers la socket.

    Voilà un schéma général de ce qui se passe :
    Exemple :
    (n) = codé sur n octets

    - FRAME : header(1)/id(1)/n(1)/data0/data1/.../dataN
    - data0 : type(1)/bloc(length)

    header : octet fixe (0xFF)
    id : identifiant sur 1 octet
    n : nombre de bloc "data" qu'il y a dans la trame.
    type : type de la donnée contenu dans le champ "vals" de la structure data
    (exemple : 1 = int8 / 2=int16 / 3=int32/ 4=uint8 /.... / 10 = string)
    bloc : chaine de caractère contenant soit les bits correspondant à l'entier à envoyer (si int16, char[1] = MSB / char[0] = LSB par exemple)

    serveur.h
    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
     
    //un client contient d'autres données dont la socket (pas super important de savoir l'utilité ici)
    struct Client
    {
        char name[128];
     
        int id;
        unsigned char tab[3];
        int a;
        int b;
        int c;
        int d;
     
        int mysocket;
    }
     
    struct data
    {
        char* vals;
        char type;
        char length;
        char length_string;
    };
     
    struct frame
    {
        char header;
        char id;
        char n; //nombre de structure "data" dans la "frame"
        struct data* bloc;
    };
    serveur.c
    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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
     
    //créer un bloc à insérer dans frame
    void creer_bloc(struct data* d, char type, char* v, int taille)
    {
        d->vals = malloc(taille);
        d->type = type;
     
        if(type != STRING)
        {
            d->length = taille;
            d->length_string = 0;
            memcpy(d->vals, v, taille);
        }
        else
        {
            d->length = 0;
            d->length_string = taille;
            strcpy(d->vals, v);
        }
     
    }
     
    //créer une trame à partir d'un bloc
    void creer_trame(struct frame* f, char h, char id, char n, struct data* d)
    {
        f->header = h;
        f->id = id;
        f->n = n;
        if(d == NULL)
            f->bloc = NULL;
        else
        {
            f->bloc = malloc(sizeof(struct data));
            memcpy(f->bloc, d, sizeof(*d));
        }
    }
     
    //ajouter un bloc dans une trame existante
    void ajouter_bloc_dans_trame(struct frame* f, struct data* d, int decalage)
    {
        if(d->type == STRING)
        {
            f->bloc[decalage].vals = malloc(sizeof(d->length_string));
            memcpy(f->bloc[decalage].vals, d->vals, d->length_string);
        }
        else
        {
            f->bloc[decalage].vals = d->vals;
        }
        f->bloc[decalage].type = d->type;
        f->bloc[decalage].length = d->length;
        f->bloc[decalage].length_string = d->length_string;
    }
     
    //FONCTION DE TEST : envoi chaque trame décrivant chaque client à tous les clients à chaque fois
    void test(struct Client** c)
    {
        int i, j;
        char* buffer;
        struct data* d = malloc(sizeof(struct data));
        struct frame* t = malloc(sizeof(struct frame));
     
        for(i=0 ; j<NOMBRE_CLIENT ; i++)
            {
            for(j=0 ; j<NOMBRE_CLIENT ; j++)
            {
                //ajouter un bloc contenant un UINT16
                buffer = malloc(2);
                EntierToBinaire(c[j]->id, buffer, UINT16);
                creer_bloc(d, UINT16, buffer, 2); //2 : 2 octets pour un UINT16
                creer_trame(t, 0xFF, 0x40, 9, d); //il y aura 9 "bloc" (struct data)     dans la trame
     
                //ajouter un bloc contenant un STRING
                creer_bloc(d, STRING, c[j]->name, strlen(c[j]->name));
               ajouter_bloc_dans_trame(t, d, 1);
     
                //ajouter un block contenant un UINT8
                buffer = malloc(1);
                EntierToBinaire(c[j]->tab[0], buffer, UINT8);
                creer_bloc(d, UINT8, buffer, 1);
                ajouter_bloc_dans_trame(t, d, 2);
     
                //ajouter un block contenant un UINT8
                buffer = malloc(1);
                EntierToBinaire(c[j]->tab[1], buffer, UINT8);
                creer_bloc(d, UINT8, buffer, 1);
                ajouter_bloc_dans_trame(t, d, 3);
     
                //ajouter un block contenant un UINT8
                buffer = malloc(1);
                EntierToBinaire(c[j]->tab[2], buffer, UINT8);
                creer_bloc(d, UINT8, buffer, 1);
                ajouter_bloc_dans_trame(t, d, 4);
     
                //ajouter un bloc contenant un UINT16
                buffer = malloc(2);
                EntierToBinaire(c[j]->a, buffer, UINT16);
                creer_bloc(d, UINT16, buffer, 2); //2 : 2 octets pour un UINT16
                ajouter_bloc_dans_trame(t, d, 5);
     
                //ajouter un bloc contenant un UINT16
                buffer = malloc(2);
                EntierToBinaire(c[j]->b, buffer, UINT16);
                creer_bloc(d, UINT16, buffer, 2); //2 : 2 octets pour un UINT16
                ajouter_bloc_dans_trame(t, d, 6);
     
                //ajouter un block contenant un UINT8
                buffer = malloc(1);
                EntierToBinaire(c[j]->c, buffer, UINT8);
                creer_bloc(d, UINT8, buffer, 1);
                ajouter_bloc_dans_trame(t, d, 7);
     
                //ajouter un block contenant un UINT8
                buffer = malloc(1);
                EntierToBinaire(c[j]->d, buffer, UINT8);
                creer_bloc(d, UINT8, buffer, 1);
                ajouter_bloc_dans_trame(t, d, 8);
     
     
     
                envoyer_trame(c[i]->mysocket, t);
            }
        }
    }

    Le résultat obtenu est :
    - tous les champs sont valides et correspondent bien aux données envoyées SAUF le champ correspond au STRING. Il m'affiche une chaine correspondant à rien. J'ai effectué toutes les vérifications, la chaine dans la structure client est bien initialisé et possède une valeur !

    Merci à tout ceux qui m'ont lu et qui pourront m'aider ! Je ne sais vraiment plus où chercher.

  2. #2
    Membre Expert Avatar de Trademark
    Profil pro
    Inscrit en
    Février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 762
    Par défaut
    Est-ce que le problème se trouve de C vers JAVA ou de JAVA vers C ? Avez-vous essayer d'envoyer une chaine du type "aaaaaaaaaa" et d'afficher le résultat obtenu pour voir si il y avait répétition ? Il se peut que ça soit un problème d'encodage des caractères. Vu que java utilise 2 bytes et C 1 byte (char) pour chaque caractères.

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Août 2010
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 7
    Par défaut
    Merci pour votre réponse !

    Le problème se situe au niveau du C. Parce qu'en fait, j'utilise une fonction d'affichage de mes trames et j'effectue cette affichage à la fin de la fonction "test", à la fin à l'intérieur de la seconde boucle for. En fait, le programme est beaucoup plus long que ce que j'ai mis ci-dessus. J'ai juste recopié la fonction cause un bug. Avant cette trame, j'envoie des trames plus courte (n=2) avec des strings et tout marche parfaitement.

    Ce qui étonnant, c'est que si j'envoie le STRING avant le UINT16 dans la fonction "test", le string s'affiche correctement mais le UINT16 possède une valeur incorrecte (~20000 alors que c'est censé être égale à 0, 1 ou 2 dans mon programme).

    C'est vrai que j'avais oublié cette subtilité pour le JAVA, mais vu que j'utilise :
    - DataOutputStream avec writeUTF(string);
    - envoi sur la socket avec : writeBytes

    Je pensais qu'il n'y aurait pas ce problème, si ?

    EDIT :
    public final void writeBytes(String s)
    throws IOException
    Writes out the string to the underlying output stream as a sequence of bytes. Each character in the string is written out, in sequence, by discarding its high eight bits. If no exception is thrown, the counter written is incremented by the length of s.

    Arf dommage, donc ce n'est pas le problème :S Merci pour votre aide

  4. #4
    Membre Expert Avatar de Trademark
    Profil pro
    Inscrit en
    Février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 762
    Par défaut
    Je ne sais pas, c'était juste une idée, mais faites des tests en envoyant de petite donnée (envoie de 1 byte via le client java, est-ce que le serveur C reçoit 1 ou 2 octets ?).

    Ensuite je m'étonne que vous n'ayez pas de segfault. Dans votre fonction "test", vous créer un pointeur sur data et dans "creer_bloc" vous n'initialisez pas cette zone mémoire. En bref:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    struct data* d;
    d->vals = malloc(2);
     
    // Au lieu de :
    struct data* d = malloc(sizeof(struct data));
    d->vals = malloc(2);
    //...
    C'est une erreur récurrente qui revient aussi dans la création d'une trame. Je ne sais pas si ça résoudra votre problème mais c'est toujours un élément de réponse.

    De plus, si je peux me permettre une remarque, essayer d'utiliser des noms de variables plus clair, quitte à qu'ils soient plus long. Et éviter l'amalgame entre l'anglais et le français, c'est toujours quelque chose qui n'est pas très beau.

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Août 2010
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 7
    Par défaut
    Arf oui ! Je vous prie de m'excuser, le manque de sommeil a eu raison de mes neurones.
    En fait, j'ai utilisé des noms de fonctions/variables différents dans le vrai programme. J'ai raccourcis/simplifié ces noms parce que j'ai dû recopier tout le code au clavier (pas de copier/coller) à cause de certaines contraintes matériels... Sinon je prend en note votre remarque sur l'anglais/français. Vous avez tout à fait raison et je dois avouer que je n'y faisais pas vraiment attention.
    Sinon dans la recopie du code, j'avais effectivement oublié l'initialisation des structures mais dans le vrai code, j'ai bien mis ça dans la fonction "test" :
    struct data* d = malloc(sizeof(struct data));
    struct frame* t = malloc(sizeof(struct frame));

    Je viens de vérifier le code à nouveau, et je ne crois pas avoir fais d'autres erreurs d'inattention.

    Je vous mets un affichage résultant de l'exécution du code ci-dessus, cela pourra peut-être aider :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    { 0xFFFFFFFF, 0x40, 9, uint16 0, string nom1, uint8 3, uint8 173, uint8 10, uint16 250, uint16 250, uint8 0 }
     
    { 0xFFFFFFFF, 0x40, 9, uint16 1, string 0X180XFFFFFFF+0X90X110X10080XFFFFFF85, uint8 152, uint8 215, uint8 182, uint16 238, uint16 250, uint8 0 }
     
    [.....]
    La première trame est entièrement correcte. (j'ai vérifié la valeur de chaque champ et ce sont bien les valeurs attendues).
    En revanche, la deuxième trame est erronée à partir du champ string. (les champs précédents sont correctes).

    Merci pour votre aide !

    PS : dans ma fonction d'affichage, j'ai demandé d'afficher la valeur hexadécimal des caractères < à 'a' et > à 'z', cela vient de là les 0X etc je pense.

    EDIT : normalement, les chaines correspondant aux noms font 10 caractères dans mon programme. J'ai testé aussi la largeur (length_string) de la chaine corrompue, et elle fait bien 10 caractères.

  6. #6
    Membre Expert Avatar de Trademark
    Profil pro
    Inscrit en
    Février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 762
    Par défaut
    Il y a encore plusieurs choses à dire.

    1. Vous ne libérez jamais la mémoire allouée.
    2. Dans votre structure data, pourquoi utiliser un champ length et un autre spécifique aux string ? Quand ils sont sous formes de bytes, ils ont tous la même unité de mesure, non ?
    3. Votre fonction créer_trame prend un bloc en paramètre, ça duplique la responsabilité de cette fonction. Il vaut mieux que "créer_trame" ne crée qu'une trame justement.
    4. A ce propos, vous pensez avoir un tableau de bloc mais ce n'est pas le cas. Dans créer trame faites:
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      f->bloc = malloc(sizeof(struct data*) * n);
      Ainsi bloc sera un tableau de "n" pointeur vers des blocs. (D'ailleurs pourquoi ne pas renommer la structure data en "block" justement ?


    Il y a peut de chance que ça résolve votre problème mais j'ai besoin de plus d'indication. Faites ces expériences :

    1. Envoyer le string "aaaa" du client vers le serveur et afficher.
    2. Envoyer le string "aaaa" du serveur vers le client et afficher.


    N'afficher pas sous forme hexédécimale mais juste sous forme entière.

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Août 2010
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 7
    Par défaut
    Alors concernant les problèmes :

    Vous ne libérez jamais la mémoire allouée
    Je ne vais pas vous cacher que j'ai essayé et que finalement j'ai laissé ça de côté pour plus tard. En effet, je rencontrait pas mal des erreurs avec free + affichage de la pile sur la console. Je préférais me concentrer sur les autres problèmes avant de régler celui là.

    Je vais me pencher dessus ce soir !

    Dans votre structure data, pourquoi utiliser un champ length et un autre spécifique aux string ? Quand ils sont sous formes de bytes, ils ont tous la même unité de mesure, non ?
    Alors en fait, dans le protocole, la taille d'un type autre que STRING sera codé sur 1 octet tandis que la taille d'un type string sera codé sur 2 octets. Pour simplifier les choses (calcul dans toutes mes fonctions, trames etc) et éviter de m'embrouiller, j'ai préféré rajouter un champ dans la structure. Surtout que lorsque je détecte un type STRING (dans l'envoi ou la réception), j'utilise le champ length pour une autre raison et j'utilise le champ length_string pour la taille de la chaine. Je me doute bien que ce n'est pas très très propre mais je réserve ces modifications à l'étape d'optimisation du code lorsque tout sera fonctionnel.

    Votre fonction créer_trame prend un bloc en paramètre, ça duplique la responsabilité de cette fonction. Il vaut mieux que "créer_trame" ne crée qu'une trame justement.
    Je viens de modifier tout mon code pour corriger cela. Je vous le met ci-dessous ! C'est vrai que ça parait plus clair maintenant.

    A ce propos, vous pensez avoir un tableau de bloc mais ce n'est pas le cas.
    Vous avez tout à fait raison, j'aurais pu mettre des années à me rendre compte de ça... J'ai corrigé cette erreur dans la création d'une trame !

    Envoyer le string "aaaa" du client vers le serveur et afficher.
    Envoyer le string "aaaa" du serveur vers le client et afficher.
    Voilà le résultat :
    - "aaaa" : client->serveur
    => affiche : { 0xFF, 0x40, 1, "aaaa" } sur le client java

    - "aaaa" : serveur->client
    => affiche : { 0xFF, 0x40, 1, "aaaa" } sur le serveur C

    Si j'effectue un affichage caractère par caractère sur le serveur C, j'obtiens :
    a
    a
    a
    a
    (avec le blanc à la fin qui correspond au caractère de fin de chaîne à mon avis)
    Est-ce que j'ai bien compris ce que vous vouliez ou c'est plutôt l'affichage en %d ?

    Avec toutes les modifications du programme, voici le nouveau résultat !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    { 0xFFFFFFFF, 0x40, 9, uint16 34916, string abcdefghij, uint8 3, uint8 173, uint8 10, uint16 250, uint16 250, uint8 0 }
     
    { 0xFFFFFFFF, 0x40, 9, uint16 57447, string klmnopqrst, uint8 3, uint8 173, uint8 10, uint16 250, uint16 250, uint8 0 }
     
    [.......]
    Les valeurs des STRING sont correctes ! Mais maintenant, ce sont les identifiants qui sont incorrectes. Je devrais avoir 0 et 1 alors que j'ai 34916 et 57447. Je viens d'essayer quelques modifications mais rien n'y fais. Ces champs restent erronés.

    Voilà mon nouveau code :

    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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
     
    //créer un bloc à insérer dans frame
    void creer_bloc(struct data* d, char type, char* v, int taille)
    {
        d->vals = malloc(taille);
        d->type = type;
     
        if(type != STRING)
        {
            d->length = taille;
            d->length_string = 0;
            memcpy(d->vals, v, taille);
        }
        else
        {
            d->length = 0;
            d->length_string = taille;
            strcpy(d->vals, v);
        }
     
    }
     
    //créer une trame à partir d'un bloc
    void creer_trame(struct frame* f, char h, char id, char n)
    {
        f->header = h;
        f->id = id;
        f->n = n;
     
        f->bloc = malloc(sizeof(struct data*) * n);
    }
     
    //ajouter un bloc dans une trame existante
    void ajouter_bloc_dans_trame(struct frame* f, struct data* d, int decalage)
    {
        f->bloc[decalage].type = d->type;
        f->bloc[decalage].length = d->length;
        f->bloc[decalage].length_string = d->length_string;
     
        if(d->type == STRING)
            f->bloc[decalage].vals = malloc(sizeof(d->length_string));
        else
            f->bloc[decalage].vals = = malloc(sizeof(d->length));
        strcpy(f->bloc[decalage].vals, d->vals);
    }
     
    //FONCTION DE TEST : envoi chaque trame décrivant chaque client à tous les clients à chaque fois
    void test(struct Client** c)
    {
        int i, j;
        char* buffer;
        struct data* d = malloc(sizeof(struct data));
        struct frame* t = malloc(sizeof(struct frame));
     
        for(i=0 ; j<NOMBRE_CLIENT ; i++)
            {
            for(j=0 ; j<NOMBRE_CLIENT ; j++)
            {
                //ajouter un bloc contenant un UINT16
                buffer = malloc(2);
                EntierToBinaire(c[j]->id, buffer, UINT16);
                creer_bloc(d, UINT16, buffer, 2); //2 : 2 octets pour un UINT16
                creer_trame(t, 0xFF, 0x40, 9); //il y aura 9 "bloc" (struct data)     dans la trame
                ajouter_bloc_dans_trame(t, d, 0);
     
                //ajouter un bloc contenant un STRING
                creer_bloc(d, STRING, c[j]->name, strlen(c[j]->name));
               ajouter_bloc_dans_trame(t, d, 1);
     
                //ajouter un block contenant un UINT8
                buffer = malloc(1);
                EntierToBinaire(c[j]->tab[0], buffer, UINT8);
                creer_bloc(d, UINT8, buffer, 1);
                ajouter_bloc_dans_trame(t, d, 2);
     
                //ajouter un block contenant un UINT8
                buffer = malloc(1);
                EntierToBinaire(c[j]->tab[1], buffer, UINT8);
                creer_bloc(d, UINT8, buffer, 1);
                ajouter_bloc_dans_trame(t, d, 3);
     
                //ajouter un block contenant un UINT8
                buffer = malloc(1);
                EntierToBinaire(c[j]->tab[2], buffer, UINT8);
                creer_bloc(d, UINT8, buffer, 1);
                ajouter_bloc_dans_trame(t, d, 4);
     
                //ajouter un bloc contenant un UINT16
                buffer = malloc(2);
                EntierToBinaire(c[j]->a, buffer, UINT16);
                creer_bloc(d, UINT16, buffer, 2); //2 : 2 octets pour un UINT16
                ajouter_bloc_dans_trame(t, d, 5);
     
                //ajouter un bloc contenant un UINT16
                buffer = malloc(2);
                EntierToBinaire(c[j]->b, buffer, UINT16);
                creer_bloc(d, UINT16, buffer, 2); //2 : 2 octets pour un UINT16
                ajouter_bloc_dans_trame(t, d, 6);
     
                //ajouter un block contenant un UINT8
                buffer = malloc(1);
                EntierToBinaire(c[j]->c, buffer, UINT8);
                creer_bloc(d, UINT8, buffer, 1);
                ajouter_bloc_dans_trame(t, d, 7);
     
                //ajouter un block contenant un UINT8
                buffer = malloc(1);
                EntierToBinaire(c[j]->d, buffer, UINT8);
                creer_bloc(d, UINT8, buffer, 1);
                ajouter_bloc_dans_trame(t, d, 8);
     
     
     
                envoyer_trame(c[i]->mysocket, t);
            }
        }
    }
    Merci encore pour le temps que vous me consacrez !

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Août 2010
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 7
    Par défaut
    Problème résolu !

    Dans la fonction "test", j'ai déplacé la déclaration "char* buffer;" dans la seconde boucle "for" et j'ai rajouté "free(buffer)" à la fin de cette boucle.

    Mais je ne comprends pas vraiment pourquoi, si quelqu'un pouvait m'expliquer, ça serait génial.

    Je pense que c'est dû au fait que je fais des malloc successifs sur le même "char* buffer". Je pensais qu'on avait le droit, non ?

  9. #9
    Membre Expert Avatar de Trademark
    Profil pro
    Inscrit en
    Février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 762
    Par défaut
    Je ne sais pas exactement pourquoi ça marche maintenant. Mais de toute évidence, c'est par chance que la fonction free() arrange quelque chose.

    Dans tous les cas, vous ne libérez toujours pas correctement la mémoire allouée. Vous devez le faire après chaque "malloc".

    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
                //ajouter un bloc contenant un UINT16
                buffer = malloc(2);
                EntierToBinaire(c[j]->id, buffer, UINT16);
                creer_bloc(d, UINT16, buffer, 2); //2 : 2 octets pour un UINT16
                creer_trame(t, 0xFF, 0x40, 9); //il y aura 9 "bloc" (struct data)     dans la trame
                ajouter_bloc_dans_trame(t, d, 0);
                free(buffer);
    
                //ajouter un bloc contenant un STRING
                creer_bloc(d, STRING, c[j]->name, strlen(c[j]->name));
               ajouter_bloc_dans_trame(t, d, 1);
    
                //ajouter un block contenant un UINT8
                buffer = malloc(1);
                EntierToBinaire(c[j]->tab[0], buffer, UINT8);
                creer_bloc(d, UINT8, buffer, 1);
                ajouter_bloc_dans_trame(t, d, 2);
                free(buffer);
    // Etc.
    A mon avis, vous risquez d'avoir bientôt une autre erreur. Car on ne résout pas un problème de ce type en libérant la mémoire. N'oubliez pas non plus de libérer les blocs et les trames une fois envoyée.

    Vous pouvez vérifiez les fuites de mémoire dans votre programme grâce à l'utilitaire Valgrind. Une fois installé, il suffit de faire (en console sous Linux) :

    Et vous aurez un diagnostique.

    Bonne continuation

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    Août 2010
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 7
    Par défaut
    Merci beaucoup pour votre aide.

    Vous aviez tout à fait raison, j'ai rencontré le même type d'erreur en voulant envoyer une trame de 17 champs de données. Je viens de le résoudre en allouant le "char* vals" de chaque bloc dans creer_trame directement après le malloc de la structure.

    J'ai essayé valgrind et ça ne me rassure pas trop. Il me dit que j'ai "2676 errors from 190 contexts".

    Je vais essayer de regarder ça de plus près !

    Bonne soirée !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Installation de Java sous Linux
    Par hubux dans le forum Langage
    Réponses: 3
    Dernier message: 11/11/2006, 17h26
  2. aide java sous linux
    Par blackcrow1981 dans le forum Langage
    Réponses: 2
    Dernier message: 10/07/2006, 17h41
  3. Executable Java sous Linux
    Par menuge dans le forum Général Java
    Réponses: 1
    Dernier message: 03/05/2006, 10h48
  4. Java sous linux
    Par ingenieur2008 dans le forum Applications et environnements graphiques
    Réponses: 2
    Dernier message: 23/01/2006, 14h22

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