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 :

Ellipse, comment ça fonctionne?


Sujet :

C++

  1. #1
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 292
    Billets dans le blog
    2
    Par défaut Ellipse, comment ça fonctionne?
    Bonjour à tous,

    je me retrouve avec un problème à résoudre, et j'ai bien peur que la solution la plus élégante pour le faire soit l'utilisation d'une ellipse.
    Cependant, j'ai du mal avec cette étrange chose. Voici ma fonction:
    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
    #include <string>
    #include <iostream>
     
    using namespace std;
     
    // cette fonction est censé prendre une nombre quelconque de string en paramètre et les afficher
    void Write(std::string args, ...)
    {
    	string str;
    	va_list vl;
     
    	str=args;
     
    	va_start(vl,args);
     
    	do {
    		cout << str;
    		str=va_arg(vl, string);
    	} while (!str.empty());
     
    	va_end(vl);
    	cout << endl;
    }
    Lorsque je tente d'utiliser ma fonction ainsi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    int main(int argc, char* argv[])
    {
    	Write(string("toto"), string("titi"), string("tata"));
     
    	return 0;
    }
    Le programme plante à la dernière itération de la boucle do/while dans la fonction Write(), à la ligne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    str=va_arg(vl, string);
    Le débugger m'amène dans le fichier memcpy.asm à la ligne
    rep movsd ;N - move all of our dwords
    avec le message d'erreur suivant:
    Unhandled exception at 0x10231f1a (msvcr80d.dll) in Test1.exe: 0xC0000005: Access violation reading location 0x0a5cf99c.
    Avez-vous une idée de ce qui cloche?

  2. #2
    Membre expérimenté
    Inscrit en
    Décembre 2003
    Messages
    272
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 272
    Par défaut
    Ta routine attend une chaine vide pour sortir de la boucle. Ton appel doit être :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Write(string("toto"), string("titi"), string("tata"), string());

  3. #3
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Tu ne peux pas utiliser les varags pour des non-PODs.

  4. #4
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 292
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par loufoque
    Tu ne peux pas utiliser les varags pour des non-PODs.
    Bah pourtant ça fonctionne avec la solution proposée par Ulmo. Code compilé sous windows avec VS2005.

  5. #5
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 292
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Ulmo
    Ta routine attend une chaine vide pour sortir de la boucle. Ton appel doit être :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Write(string("toto"), string("titi"), string("tata"), string());
    Merci
    N'existet-il pas une feinte pour se passer de ce dernier élément?

  6. #6
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Pourquoi ne pas utiliser un flux (ou tout du moins une solution à base de chaînage d'appels) ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MonFlux << "toto" << "titi" << "tata";

  7. #7
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 292
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Laurent Gomila
    Pourquoi ne pas utiliser un flux (ou tout du moins une solution à base de chaînage d'appels) ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MonFlux << "toto" << "titi" << "tata";
    Car en fait, dans mon cas,
    1) ce ne seront pas des string que j'aurais en paramètre, mais des classes que je vais devoir créer.
    2) je ne vais pas faire un cout dessus, mais je vais devoir faire quelques traitements dessus.

    Ensuite, j'ai d'autres difficultés, c'est que ma fonction Write devra prendre des arguments de type différents. Je pense donc que je vais devoir créer mes propres types qui héritent d'une interface IDummy et mon Write va se présenter ainsi: void Write(IDummy dum1 ...);

    C'est absolument horrible, mais je ne vois pas comment je pourrais faire autrement.

  8. #8
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Par défaut
    Tu peux :
    - passer un std::vector<Dummy*>& pour éviter cette horreur
    - utiliser un visiteur pour tes traitements plutôt
    - ...

  9. #9
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 292
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Miles
    - passer un std::vector<Dummy*>& pour éviter cette horreur
    Oui en effet, tout simplement...
    pas la grande forme moi ^^

  10. #10
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut
    Ouaip. Parce que march'ra paas!

    C'est pas vraiment déterministe le non-POD dans les fonctions à ellipse. Avec un même compilo, pour une même plateforme cible, la même fonction, parfois le résultat espéré est obtenu, parfois ça crashe de toute beauté.

    De toutes façons, avec ton héritage, tu aurais dû obligatoirement passer des pointeurs sur ton interface (ben ouais, la sémantique de copie n'est pas vraiment compatible avec des hiérarchies polymorphes), et du coup tu aurais pû t'en sortir.
    Mais franchement!
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Pourquoi ne pas faire une classe qui s'emploierait comme un flux ?
    Je ne vois rien qui l'en empêche (c'est indépendant de tes contraintes 1 et 2), sauf si "3: le traitement d'une string dépend des strings qui la suivent (ou de leur absence)".

    Si tu n'as pas cette contrainte, alors rien ne t'empêche de faire "Write("toto"); Write("tata"); Write("titi");"
    que tu peux, si tu le souhaites, transformer en "MonObjetPerso << "toto" << "tata" < "titi";"Je ne peux pas faire comme ça, car en effet, mon traitement dépend du nmobre d'objets passés en paramètre. En fait, j'effectue une sorte de sérialization (ou formattage) avec les données contenues dans les classes que je reçois en paramètre.

    Au final, j'ai fais un truc assez moche, mais qui est plus simple à utiliser. J'ai appris, assez tard hier soir, que je n'aurais jamais plus de 4 paramètres dans cette fonction en fait. J'ai donc surchargé ma fonction 4 fois:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Write(MonInterface* i);
    Write(MonInterface* i1, MonInterface* i2);
    Write(MonInterface* i1, MonInterface* i2, MonInterface* i3);
    Write(MonInterface* i1, MonInterface* i2, MonInterface* i3, MonInterface* i4);
    C'est assez moche (notamment en terme de maintenabilité), mais finalement, ça simplifie l'utilisation, ce qui était la contrainte la plus importante.
    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.

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Citation Envoyé par Luc Hermitte
    Ouaip. Parce que march'ra paas!

    C'est pas vraiment déterministe le non-POD dans les fonctions à ellipse. Avec un même compilo, pour une même plateforme cible, la même fonction, parfois le résultat espéré est obtenu, parfois ça crashe de toute beauté.
    Exact.
    Sous Visual par exemple, le contenu du type est directement empilé comme si c'était une structure POD. C'est pourquoi les CString de MFC contiennent juste un pointeur sur les caractères, pour passer pour une simple chaîne dans un printf() ou un CString::Format().
    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.

  13. #13
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Les varargs avec des non-PODs c'est du comportement indéfini.
    Après, de manière réaliste, on se doute bien que ça marche quand même, sauf que la copie se fait bit à bit au lieu d'utiliser le constructeur par recopie.
    Ce qui est pas plus mal dans ton cas en fait puisque tu ne modifies pas la chaîne.

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

Discussions similaires

  1. Compilateur asm, comment ça fonctionne ?
    Par AsmCode dans le forum Assembleur
    Réponses: 21
    Dernier message: 29/07/2005, 23h59
  2. Comment faire fonctionner une scroll bar ???
    Par toto4650 dans le forum MFC
    Réponses: 10
    Dernier message: 18/07/2005, 16h47
  3. [JToolTip] comment ca fonctionne ?
    Par Terminator dans le forum Composants
    Réponses: 2
    Dernier message: 29/05/2005, 15h18
  4. [Chat] Comment faire fonctionner Flash 7 sous Debian ?
    Par piff62 dans le forum Evolutions du club
    Réponses: 22
    Dernier message: 07/03/2005, 15h27
  5. comment faire fonctionner l'exe sur une autre machine
    Par brian79 dans le forum C++Builder
    Réponses: 8
    Dernier message: 28/05/2004, 14h00

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