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

Langage C++ Discussion :

Retourner une union


Sujet :

Langage C++

  1. #1
    Membre éclairé
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juin 2004
    Messages : 516
    Points : 706
    Points
    706
    Par défaut Retourner une union
    Bonjour,

    j'ai un problème pour retourner une union depuis une fonction. Voici un petit programme qui met en évidence le problème et qui crashe lorsque la fonction f retourne u.

    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
    #include<stdio.h>#include<stdlib.h>
    #include <string>
     
    using namespace std;
     
    union uni
    {
        struct
        {
            int v1;
            string v2;
        };
        struct
        {    
            string v3;
            char v4;
            int v5;
        };
    };
     
    uni f()
    {
        uni u;
        u.v1 = 1;
        u.v2 = "Hello";
        return u;
    }
     
    int main ()
    {
        uni u=f();
        return 0;
    }

    Je travaille avec visual studio => compilateur MS
    Le message d'erreur est le suivant:
    Exception de première chance à 0x0f94797f (msvcp90d.dll) dans bidon.exe : 0xC0000005: Violation d'accès lors de l'écriture à l'emplacement 0x00000001.Exception non gérée à 0x0f94797f (msvcp90d.dll) dans bidon.exe : 0xC0000005: Violation d'accès lors de l'écriture à l'emplacement 0x00000001.
    Je ne comprends pas quel est le problème avec la mémoire. Pourtant la taille de l'union est connue du compilateur et le résultat est passé par la pile. Le fait que l'union contienne des string ne doit pas modifier sa taille car la partie variable de la chaine (les caractères donc) doit se trouver dans le tas.
    Merci d'avance pour vos suggestions

  2. #2
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Et si tu attrapais l'exception?

    Que dit ton débugger?
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  3. #3
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    pour moi, c'est la string, parce que justement elle contient de la mémoire sur le tas.
    Précisément c'est la copie de l'union qui pose soucis.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  4. #4
    Membre éclairé
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juin 2004
    Messages : 516
    Points : 706
    Points
    706
    Par défaut
    Merci pour votre aide.
    Et si tu attrapais l'exception?
    Je ne connais pas son type.
    Que dit ton débugger?
    Ca plante dans la DLL, donc difficile de savoir. Lorsque je faire un pas à pas détaillé sur le return, ceci s'affiche:
    Exception non gérée à 0x1000797f (msvcp90d.dll) dans bidon.exe : 0xC0000005: Violation d'accès lors de l'écriture à l'emplacement 0x00000001
    .
    pour moi, c'est la string, parce que justement elle contient de la mémoire sur le tas.
    Précisément c'est la copie de l'union qui pose soucis.
    Hé oui, les caractère de la chaine ne sont pas copiés.
    En passant une référence, plus de copie et plus de plantage.
    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
    void f(uni& u){
    	u.v1 = 1;
    	cout << sizeof(uni) << endl;
    	u.v2 = "Hello";
    	cout << sizeof(uni) << endl;
    }
     
     
     
     
    int main ()
    {
    	uni u;
    	f(u);
    	return 0;
    }
    Je vérifie sur mon vrai code avant de marquer comme résolu.

  5. #5
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Une union est en général copiée par une copie directe de sa surface en mémoire.
    Le pointeur que la string contient est copié, et lorsque l'union intérieure à la fonction est détruite, la mémoire est détruite.
    Lorsque l'union extérieur est détruite, la mémoire est a nouveau détruite (double destruction).
    Toute utilisation de la string entre temps serait une erreur.

    Avec un peu d'optimisation, le compilateur devrait pouvoir utiliser la RVO, et créer directement l'union dans la variable retournée.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  6. #6
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 565
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 565
    Points : 7 648
    Points
    7 648
    Par défaut
    Bonjour,

    Ce qui m'échappe c'est que cela puisse compiler.
    Il est possible des mettre des objets non triviaux dans une union, mais cela impose de nombreuses contraintes.
    L'union doit impérativement définir les procédures forcément effacées (La string ne peut plus se copier, ni se construire, ni se détruire!) l'union n'a ni constructeur, ni destructeur, ni constructeur ou opérateur de copie utilisable
    De plus l'union contient des structs anonymes et pas un choix entre 2 struct, donc la nature même de l'objet ne parait pas claire.
    Si on écrit le code suivant, il y aura explication sur l'erreur par le compilateur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    union uni
    {
        struct 
        {
            int v1;
            string v2;
        } s1;
        struct
        {    
            string v3;
            char v4;
            int v5;
        } s2;
    };
    Quel compilateur est utilisé?

  7. #7
    Membre éclairé
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juin 2004
    Messages : 516
    Points : 706
    Points
    706
    Par défaut
    C'est le compilateur d'origine de visual studio, en l'occurrence VS2005

  8. #8
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Ne pourrais-tu essayer de passer à un compilateur moins antique (il y a eu au moins 4 versions majeurs de Visual depuis 2005), qui aurait le bon goût de se rapprocher de la norme?

    Par exemple, Visual 2013 ou 2015, pour rester chez MS, ou bien un mingw-gcc
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  9. #9
    Membre éclairé
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juin 2004
    Messages : 516
    Points : 706
    Points
    706
    Par défaut
    oui bien sur:

    0 error, 0 warning sous VS2013.

    Dans la variable u de la fonction main, je récupère la bonne valeur pour chacun des champs.

  10. #10
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Curieux que ça compile sur un truc aussi périmé.
    D'après ce que je vois sur SO http://stackoverflow.com/questions/3...g-inside-union les union étaient réservés aux POD auparavant, et ça a été assoupli avec C++11 https://en.wikipedia.org/wiki/C%2B%2...tricted_unions
    Et VS2005 implémente surement C++98, peut-être une partie de C++03, ils étaient vraiment lents auparavant à implémenter les normes (on râle encore, mais ils se sont beaucoup améliorés )
    Tu peux aussi apparemment définir constructeur/destructeur pour ton union, comme pour une simple struct/class.
    Ca reste un objet un peu spécial que je n'ai quasi jamais utilisé, et que dans des circonstances (très) simples.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

Discussions similaires

  1. Réponses: 5
    Dernier message: 15/02/2005, 18h07
  2. fonction retournant une valeur
    Par ryan dans le forum ASP
    Réponses: 4
    Dernier message: 06/09/2004, 17h45
  3. Réponses: 1
    Dernier message: 29/08/2004, 19h45
  4. Retourner une valeur avec une fonction
    Par stephtbest dans le forum ASP
    Réponses: 4
    Dernier message: 31/10/2003, 16h37
  5. [MFC] Retourner une liste d'objets
    Par 1cado dans le forum MFC
    Réponses: 10
    Dernier message: 28/07/2003, 12h11

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