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++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre chevronné
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2004
    Messages
    539
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juin 2004
    Messages : 539
    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

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    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 202
    Par défaut
    Et si tu attrapais l'exception?

    Que dit ton débugger?

  3. #3
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    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 202
    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.

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

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juin 2004
    Messages : 539
    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

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    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 202
    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.

  6. #6
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 600
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    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 600
    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é?

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