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 :

Pb affectation champs d'une struct passée en pointeur


Sujet :

C++

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    499
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 499
    Par défaut Pb affectation champs d'une struct passée en pointeur
    Bonjour,

    j'ai un ptit souci avec une struct passée en pointeur en argument d'une méthode
    et en fait, elle n'est pas mise à jour au retour,
    je sais pas trop comment ça se fait...

    donc si vous pourriez me donner un ptit coup de pouce ...

    Alors déjà, attention,
    ça peut paraître un peu barbare...
    mais j'utilise des types définis dans une librairie C...


    Donc, j'ai 2 structures :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    struct Message{
        unsigned char  nature;
        char              nomUtilisateur[MAX_SIZE];
        unsigned short periode;
        unsigned char  data;};
     
    struct Unite{
        unsigned short longueur;
        Message    mess;};
    J'ai une méthode qui me sert à remplir une structure 'Unite' :
    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
    MaMethode(unsigned short *lgMess, Message *mess)
    {
        unsigned short lgData;
        unsigned char *donnees;
     
        //...calcul de la longueur...
        *lgMess = sizeof(Message) - 1 + lgData;
     
       // allocation de la structure du message
       mess = (Message*) malloc(*lgMess);
       (void) memset(mess, 0, *lgMess);
     
       // affectation des champs de la structure
       mess->nature = ...
       StringCbCat(mess->nomUtilisateur, MAX_SIZE, "nomUtilisateur");
     
       donnees = new unsigned char[lgData];
       //... remplissage du tableau...
     
       //copie dans le message
       memcpy(&mess->data, donnes, lgData);
     
       delete[] donnees;
    }
    Et donc, quand j'appelle cette méthode :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Unite monUnite;
     
    MaMethode(&monUnite.longueur, &monUnite.mess);
    eh ben, le champ 'longueur' est bien à jour
    mais aucun champ de la struct 'mess'

    Pourtant, quand je rentre en debug,
    ça paraît tout bien...


    Alors alors??
    z'avez des pistes?...

  2. #2
    Membre émérite
    Inscrit en
    Juillet 2005
    Messages
    512
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 512
    Par défaut
    Dans ta fonction alloue de l'espace pour un autre objet "Message" que tu affecte à ton pointeur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    mess = (Message*) malloc(*lgMess);
    Donc ton pointeur ne pointe plus sur l'objet que tu a passé en paramètre mais sur ce nouvel objet que tu viens de créer.

    En plus tu fait des allocations avec malloc un peu plus loin avec new, c'est vraiement un melange de C / C++

  3. #3
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    Houla, tu veux passer quelques nuits blanches avec ce code pour comprendre les futurs bugs ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    *lgMess = sizeof(Message) - 1 + lgData;
    lgData n'est pas initialisé.
    sizeof(Message) fait 4 ou 8 (c'est un pointeur) mais certainement pas ce que tu penses.

    Tu passes un pointeur sur Message en paramètre. Donc quand tu quittes ta fonction, le pointeur dans l'appelant n'est pas modifié. 2 manières de corriger cela, passer un pointeur de pointeur sur Message en paramètre ou alors retourner un pointeur sur Message en retour de fonction.
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    499
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 499
    Par défaut
    Citation Envoyé par Lucien63 Voir le message
    Dans ta fonction alloue de l'espace pour un autre objet "Message" que tu affecte à ton pointeur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    mess = (Message*) malloc(*lgMess);
    Donc ton pointeur ne pointe plus sur l'objet que tu a passé en paramètre mais sur ce nouvel objet que tu viens de créer.
    ah ouais ok,
    pff, j'suis trop nulle avec les pointeurs et les allocations mémoires

    Donc, en fait, il vaudrait mieux que je passe un autre argument pour pour le tableau de données
    et que je l'affecte au champ de ma structure ensuite, au retour de la méthode,
    un truc dans le genre, c'est ça??

    Citation Envoyé par Lucien63 Voir le message
    En plus tu fait des allocations avec malloc un peu plus loin avec new, c'est vraiement un melange de C / C++
    En ben, voui,
    c'est bien ce que je disais
    c'est un peu barbare

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    57
    Détails du profil
    Informations personnelles :
    Âge : 17
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 57
    Par défaut
    Salut,

    toujours se ramener à quelque chose de simple pour voir si le principe marche!

    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
    #include <iostream>
    using namespace std;
     
    struct Message
    {
        int a, b;
    };
     
    struct Unite
    {
        long l;
        Message mess;
    };
     
    void MaMethode(long *l, Message *mess)
    {
        *l=5;
        mess->b = 0;
        mess->a = 8;
    }
     
    int main()
    {
        Unite u;
        MaMethode(&u.l, &u.mess);
     
        cout << u.l << u.mess.b << u.mess.a << endl;
        return 0;
    }
    Donc en principe ton code marche (note qu'au lieu d'utiliser des pointeurs tu peux utiliser des références, cf faq).

    En fait ton problème c'est que tu ne touches pas à l'adresse pointée par le mess passé en argument.

    Je m'explique:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
        unsigned short lgData;
        unsigned char *donnees;
     
        //...calcul de la longueur...
        *lgMess = sizeof(Message) - 1 + lgData;
     
       // allocation de la structure du message
       mess = (Message*) malloc(*lgMess);
    A la dernière ligne, tu changes le contenu de la variable mess, sans avoir jamais utilisé le contenu de cette variable avant. Ta fonction se comporte exactement comme celle-ci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    MaMethode(unsigned short *lgMess)
    {
        unsigned short lgData;
        unsigned char *donnees;
     
        //...calcul de la longueur...
        *lgMess = sizeof(Message) - 1 + lgData;
     
       // allocation de la structure du message
       Message *mess = (Message*) malloc(*lgMess);
       ...
    }
    Comment résoudre ce problème?
    Bah en enlevant cette ligne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
       // allocation de la structure du message
       mess = (Message*) malloc(*lgMess);
    car *mess est déjà alloué statiquement car monUnité est bien allouée statiquement.

    Edit:

    Je me rends compte avec les posts ci-dessus que tu peux même enlever ces trois lignes:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        *lgMess = sizeof(Message) - 1 + lgData;
     
       // allocation de la structure du message
       mess = (Message*) malloc(*lgMess);
       (void) memset(mess, 0, *lgMess);
    Et qu'il faut régler le problème avec lgData.

  6. #6
    Membre émérite
    Inscrit en
    Juillet 2005
    Messages
    512
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 512
    Par défaut
    Citation Envoyé par ram-0000
    sizeof(Message) fait 4 ou 8 (c'est un pointeur) mais certainement pas ce que tu penses.
    Il me semble que Message est une structure !

  7. #7
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    499
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 499
    Par défaut
    oui, Message est une structure


    en faisant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    mess = (Message*) malloc(*lgMess);
    je veux allouer une zone mémoire plus grande que celle de la structure
    afin d'y mettre mon tableau data au bout...

    Vous comprenez??...


    C'était fait comme ça dans l'appli en C dont je m'inspire...

  8. #8
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    57
    Détails du profil
    Informations personnelles :
    Âge : 17
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 57
    Par défaut
    Mais le problème c'est que monUnite.mess est allouée statiquement.

    C'est comme si tu faisais:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int a = 1;
     (&a) = malloc(sizeof(int));
    C'est absurde de faire ça, n'est-ce pas?

    Tu ne peux pas changer l'adresse de a puisque la variable est allouée statiquement.

    Et d'ailleurs, Message est toujours de la même taille:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    struct Message{
        unsigned char  nature;
        char              nomUtilisateur[MAX_SIZE];
        unsigned short periode;
        unsigned char  data;};
    Il n'a pas une taille variable, donc si tu veux en allouer un dynamiquement tu fais:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Message *pointeur = malloc(sizeof(Message));
    ou en C++:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Message *pointeur = new Message;

  9. #9
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    57
    Détails du profil
    Informations personnelles :
    Âge : 17
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 57
    Par défaut
    Si tu veux rajouter un tableau data à la fin, il faut changer ta structure:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    struct Message{
        unsigned char  nature;
        char              nomUtilisateur[MAX_SIZE];
        unsigned short periode;
        unsigned char * data; //un POINTEUR
    };
    Et alors tu procéderais comme ça:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Message mess;
    mess->data = new data[lgData+1];
    Ou alors dans un esprit C++, tu ferais de Message une classe et lui donnerais un constructeur, des fonctions membres et un destructeur pour gérer l'allocation et la libération de data.

    Ou tu utiliserais carrément des string...

  10. #10
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    499
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 499
    Par défaut
    Citation Envoyé par Dreambeliever Voir le message
    Si tu veux rajouter un tableau data à la fin, il faut changer ta structure:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    struct Message{
        unsigned char  nature;
        char              nomUtilisateur[MAX_SIZE];
        unsigned short periode;
        unsigned char * data; //un POINTEUR
    };
    Et alors tu procéderais comme ça:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Message mess;
    mess->data = new data[lgData+1];
    Je suis bien d'accord...

    mais le souci,
    c'est que ma variable de type Message,
    une fois remplie,
    je dois la passer à une des fonctions de la librairie C sous forme de tableau de char
    pour cela, il faut donc que tous les champs de la structure soient contigus dans une même zone mémoire
    et ça ne serait pas le cas avec le pointeur pour le champ data...

  11. #11
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    57
    Détails du profil
    Informations personnelles :
    Âge : 17
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 57
    Par défaut
    Donc alors faire comme ça:

    je viens de me rendre compte de ce que tu veux faire: allouer plus d'espace que prévu pour une structure et écrire ton data dans le surplus de mémoire.

    C'est possible en C, en C++ aussi bien que fortement déconseillé en C++ (car alors on ne peut pas faire d'héritage, ...), mais pas dans ce cas là car ta variable mess est déjà allouée statiquement.

    Si tu veux le faire il faut pouvoir l'allouer dynamiquement, c'est -à-dire changer la déclaration de la structure Unite pour mettre mess en pointeur (et alors utiliser un pointeur de pointeur en argument de MaMethode)

  12. #12
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    499
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 499
    Par défaut
    Pourrais-tu m'en dire plus
    pleeaaaaaaase

  13. #13
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    57
    Détails du profil
    Informations personnelles :
    Âge : 17
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 57
    Par défaut
    En reprenant ton code et en utilisant une référence sur pointeur au lieu d'un double pointeur:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    struct Unite{
        unsigned short longueur;
        Message   * mess;
    };
     
    MaMethode(unsigned short *lgMess, Message *& mess)
    {
       ...
    }
     
    MaMethode(&monUnite.longueur, monUnite.mess);
    avec un double pointeur:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    struct Unite{
        unsigned short longueur;
        Message   * mess;
    };
     
    MaMethode(unsigned short *lgMess, Message ** p_mess)
    {
       // utiliser (*p_mess) au lieu de mess
       ...
    }
     
    MaMethode(&monUnite.longueur, &monUnite.mess);

  14. #14
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    499
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 499
    Par défaut

    yeah,

    j'essaie ça demain
    et vous tiens au courant

  15. #15
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    499
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 499
    Par défaut
    Muchas gracias!!

    j'ai essayé avec une référence sur le pointeur,
    ça marche nickel

    trop cool,
    depuis le temps que je galérais là-dessus...

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 04/06/2007, 13h45
  2. Affecter valeur d'un champ dans une variable
    Par Sly2k dans le forum Access
    Réponses: 3
    Dernier message: 17/08/2006, 09h43
  3. Réponses: 2
    Dernier message: 21/04/2006, 12h09
  4. Réponses: 4
    Dernier message: 08/11/2005, 17h13

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