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 :

Fonctions vides et non inlinées


Sujet :

C++

  1. #1
    Membre Expert
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Par défaut Fonctions vides et non inlinées
    Hello,

    C'est un sujet qui touche à la fois au C++ et à l'assembleur, mais je pense qu'il à sa place ici. Si ce n'est pas le cas, n'hésitez pas à le déplacer dans la catégorie asm.

    Je fais un peu de reversing actuellement (et je galère comme pas possible ),
    et je suis tombé sur des fonctions un peu surprenante en assembleur.

    Je bosse sur un exe écrit à la base en C++ et compilé avec VS2010 (en release).

    Il y a des fonctions vides type
    Code asm : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    sub_vide proc near
       retn
    sub_vide endp
    Et ces fonctions vides sont appelées directement dans le code (sans passer par une vtable)
    Code asm : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    sub_xxx proc near
       // ...
       call sub_vide
       // ...
    proc_xxx endp
    Ainsi que des fonctions non inlinées mais qui devraient l'être
    Code asm : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    sub_xxx proc near
       call sub_yyy
       retn
    sub_xxx endp

    J'ai essayé de faire un code minimal (en C++) reproduisant ça, mais je n'y arrive pas
    Code c++ : 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
    struct Base {
    	virtual ~Base() { }
     
    	virtual void foo() { }
    };
     
    struct Derivee: Base {
    	virtual void foo() { std::cout << "should be easy to find me in assembly" << std::endl; }
    };
     
     
    void bar() {
    	std::cout << "before" << std::endl;
    	Base b;
    	b.foo();
    	std::cout << "after" << std::endl;
    }
     
    int main() {
     
    	bar();
     
    	Base *b = new Base;
    	b->foo();
     
    	Base *d = new Derivee;
    	d->foo();
     
    	return 0;
    }
    Mais aucun appel direct à Base::foo n'est présent dans l'exe généré, la fonction Base::foo est bien vide, mais seule la vtable de Base y fait référence (.rdata:00403214o)
    Code asm : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    .text:00401280 ; void __thiscall Base__foo(Base *this)
    .text:00401280 ?foo@Base@@UAEXXZ proc near             ; DATA XREF: .rdata:00403214o
    .text:00401280 this = ecx
    .text:00401280                 retn
    .text:00401280 ?foo@Base@@UAEXXZ endp
    Code asm : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    .rdata:00403210 ; const Base::`vftable'
    .rdata:00403210 ??_7Base@@6B@   dd offset ??_EDerivee@@UAEPAXI@Z
    .rdata:00403210                                         ; DATA XREF: Base::~Base(void)o
    .rdata:00403210                                         ; Derivee::`vector deleting destructor'(uint)+Ao ...
    .rdata:00403210                                         ; Derivee::`vector deleting destructor'(uint)
    .rdata:00403214                 dd offset ?foo@Base@@UAEXXZ ; Base::foo(void)
    .rdata:00403218                 dd offset ??_R4_Generic_error_category@std@@6B@ ; const std::_Generic_error_category::`RTTI Complete Object Locator'
    Code asm : 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
    .text:004012E0 ; =============== S U B R O U T I N E =======================================
    .text:004012E0
    .text:004012E0 ; Attributes: bp-based frame
    .text:004012E0
    .text:004012E0 ; int __cdecl main()
    .text:004012E0 _main           proc near               ; CODE XREF: __tmainCRTStartup+F8p
    .text:004012E0
    .text:004012E0 var_14          = dword ptr -14h
    .text:004012E0 var_C           = dword ptr -0Ch
    .text:004012E0 var_4           = dword ptr -4
    .text:004012E0
    .text:004012E0                 push    ebp
    .text:004012E1                 mov     ebp, esp
    .text:004012E3                 and     esp, 0FFFFFFF8h
    .text:004012E6                 push    0FFFFFFFFh
    .text:004012E8                 push    offset __ehhandler$_main
    .text:004012ED                 mov     eax, large fs:0
    .text:004012F3                 push    eax
    .text:004012F4                 sub     esp, 0Ch
    .text:004012F7                 mov     eax, ___security_cookie
    .text:004012FC                 xor     eax, esp
    .text:004012FE                 push    eax
    .text:004012FF                 lea     eax, [esp+1Ch+var_C]
    .text:00401303                 mov     large fs:0, eax
    .text:00401309                 push    ds:__imp_?endl@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@1@AAV21@@Z ; std::endl(std::basic_ostream<char,std::char_traits<char>> &)
    .text:0040130F                 mov     ecx, ds:__imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A ; _Ostr
    .text:00401315                 mov     edx, offset aBefore ; "before"
    .text:0040131A                 call    ??$?6U?$char_traits@D@std@@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@PBD@Z ; std::operator<<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,char const *)
    .text:0040131F                 mov     ecx, eax
    .text:00401321                 call    ds:__imp_??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z ; std::basic_ostream<char,std::char_traits<char>>::operator<<(std::basic_ostream<char,std::char_traits<char>> & (*)(std::basic_ostream<char,std::char_traits<char>> &))
    .text:00401327                 mov     [esp+1Ch+var_14], offset ??_7Base@@6B@ ; const Base::`vftable'
    .text:0040132F                 mov     [esp+1Ch+var_4], 0
    .text:00401337                 push    ds:__imp_?endl@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@1@AAV21@@Z ; std::endl(std::basic_ostream<char,std::char_traits<char>> &)
    .text:0040133D                 mov     ecx, ds:__imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A ; _Ostr
    .text:00401343                 mov     edx, offset aAfter ; "after"
    .text:00401348                 call    ??$?6U?$char_traits@D@std@@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@PBD@Z ; std::operator<<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,char const *)
    .text:0040134D                 mov     ecx, eax
    .text:0040134F                 call    ds:__imp_??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z ; std::basic_ostream<char,std::char_traits<char>>::operator<<(std::basic_ostream<char,std::char_traits<char>> & (*)(std::basic_ostream<char,std::char_traits<char>> &))
    .text:00401355                 push    4
    .text:00401357                 mov     [esp+20h+var_4], 0FFFFFFFFh
    .text:0040135F                 call    ds:__imp_??2@YAPAXI@Z ; operator new(uint)
    .text:00401365                 mov     ecx, eax
    .text:00401367                 add     esp, 4
    .text:0040136A                 test    ecx, ecx
    .text:0040136C                 jz      short loc_401376
    .text:0040136E                 mov     dword ptr [ecx], offset ??_7Base@@6B@ ; const Base::`vftable'
    .text:00401374                 jmp     short loc_401378
    .text:00401376 ; ---------------------------------------------------------------------------
    .text:00401376
    .text:00401376 loc_401376:                             ; CODE XREF: _main+8Cj
    .text:00401376                 xor     ecx, ecx
    .text:00401378
    .text:00401378 loc_401378:                             ; CODE XREF: _main+94j
    .text:00401378                 mov     eax, [ecx]
    .text:0040137A                 call    dword ptr [eax+4]
    .text:0040137D                 push    4
    .text:0040137F                 call    ds:__imp_??2@YAPAXI@Z ; operator new(uint)
    .text:00401385                 mov     ecx, eax
    .text:00401387                 add     esp, 4
    .text:0040138A                 test    ecx, ecx
    .text:0040138C                 jz      short loc_401396
    .text:0040138E                 mov     dword ptr [ecx], offset ??_7Derivee@@6B@ ; const Derivee::`vftable'
    .text:00401394                 jmp     short loc_401398
    .text:00401396 ; ---------------------------------------------------------------------------
    .text:00401396
    .text:00401396 loc_401396:                             ; CODE XREF: _main+ACj
    .text:00401396                 xor     ecx, ecx
    .text:00401398
    .text:00401398 loc_401398:                             ; CODE XREF: _main+B4j
    .text:00401398                 mov     eax, [ecx]
    .text:0040139A                 call    dword ptr [eax+4]
    .text:0040139D                 xor     eax, eax
    .text:0040139F                 mov     ecx, [esp+1Ch+var_C]
    .text:004013A3                 mov     large fs:0, ecx
    .text:004013AA                 pop     ecx
    .text:004013AB                 mov     esp, ebp
    .text:004013AD                 pop     ebp
    .text:004013AE                 retn
    .text:004013AE _main           endp
    Ici bar est inline, l'objet temporaire Base b est déclaré sur la pile
    Code asm : Sélectionner tout - Visualiser dans une fenêtre à part
    .text:00401327                 mov     [esp+1Ch+var_14], offset ??_7Base@@6B@ ; const Base::`vftable'
    mais aucune fonction n'est appelé (ctor par defaut, et Base::foo, supprimés par optimisation).

    Les appels b->foo(); et d->foo(); sont identiques et passent par la vtable correspondante (ce qui est normal)
    Code asm : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    .text:0040136E                 mov     dword ptr [ecx], offset ??_7Base@@6B@ ; const Base::`vftable' -> fin de Base *b = new Base; : on récupère l'adresse de la vtable de Base
    .text:00401374                 jmp     short loc_401378
    ; ..
    .text:00401378 loc_401378:                             ; CODE XREF: _main+94j
    .text:00401378                 mov     eax, [ecx]
    .text:0040137A                 call    dword ptr [eax+4] ; b->foo();
    ; ...
    .text:0040138E                 mov     dword ptr [ecx], offset ??_7Derivee@@6B@ ; const Derivee::`vftable'
    .text:00401394                 jmp     short loc_401398
    ; ...
    .text:00401398 loc_401398:                             ; CODE XREF: _main+B4j
    .text:00401398                 mov     eax, [ecx]
    .text:0040139A                 call    dword ptr [eax+4] ; d->foo();
    Bref, comment est-ce possible que des fonctions vides passent la phase d'optimisation et se retrouvent appelées directement ?
    Même question pour les fonctions qui devraient être inline ?

  2. #2
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    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 393
    Par défaut
    Je suppose que tout est dans un seul fichier source, naturellement?

    Pourrais-tu poster le fichier entier?
    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.

  3. #3
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 635
    Par défaut
    Salut,

    Une question peut être idiote, mais ne s'agirait-il pas, d'une manière ou d'une autre, d'une fonction marquant la fin d'une récursivité

    Je m'explique : Typiquement, les fonctions récursives ne peuvent pas être inline (du moins, quand elles n'utilisent pas exclusivement des constantes de compilation), "simplement" parce que le compilateur ne saurait pas déterminer combien de fois il doit copier le code correspondant. Il suffirait qu'il prévoie d'alliger mettons 5 fois le code pour que tu tombes sur une situation où il aurait fallut l'aligner six fois

    Or le principe pour gérer "sereinement" la récursivité, c'est de gérer en priorité le cas de base. On veut dire par là que la première chose que tu dois faire, c'est de trouver le cas qui permettra de sortir de la récursivité.

    Je n'aime pas particulièrement l'exemple de la factorielle quand on parle de récursivité (je trouve qu'il y a des exemples bien plus utiles à la démonstration), mais, dans le cas présent, pour te permettre de comprendre, ce dont je veux parler, ce sera quand même l'exemple le plus facile

    Si tu envisages de créer une fonction récursive qui calcule la factorielle, tu dois déterminer le cas de base : celui qui ne fera plus appel à la fonction et qui renverra une valeur déterminée. Dans l'exemple de la factorielle, le cas de base est une valeur de 1 : quand l'argument vaut 1, tu renvoies 1, sinon, tu renvoies la factorielle de argument-1.

    En C++, cela donnera le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    size_t factorielle(size_t value){
        /* ici, on teste le cas de base */
        if(value == 1){
            return 1; // quand on arrive ici, on commence à remmonter la pile d'appel
        }
        /* tout le reste tend à nous faire arriver au cas de base ;) */
        return value *factorielle(value -1 );
    }
    Mais ca, c'est un exemple vraiment simple...

    Le fait est que la récursivité peut très bien être "indirecte" : Une fonction f1 appelle la fonction f2 qui (...il peut y en avoir d'autres ) appelle la fonction f1. Et tu auras "quelque part" un if qui, au lieu d'appeler la fonction suivante fera appel à une fonction qui ne fait rien et qui provoque la sortie de la récursion.

    Cela pourrait prendre la forme de quelque chose comme
    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
    void f0(){
        /* ne fait strictement rien */
    }
    void f1(/* paramètres */){
        f2(/* paramètre (modifiés?)*/);
    }
    void f2(/* paramètres */){
        if(test)
            f0();
        else
            f3(/* paramètres */);
    }
    void f3(/* paramètres */){
        f1(/* paramètres */);
    }
    On ne le remarquera pas tout de suite (surtout si les différentes fonctions sont éparpillées dans différents fichiers) mais f0 sera la fonction qui nous sortira de la récursivité pendant que f1, f2 et f3 s'amuseront à s'appeler l'une l'autre juqu'à ce qu'il gèle en enfer si on n'arrive jamais dans le cas où le test est vérifié.

    Enfin, en théorie... Parce qu'en pratique on atteindra la limite de la pile d'appels bien avant qu'il ne gèle en enfer, et nous aurons un beau plantage

    Voilà le pourquoi de ma question : ne serait tu pas face à des fonctions qui prendraient la forme de f1, f2,...fn qui s'appellent successivement + une fonction qui ne fait rien

    Edit En sommes, je me demande si ce n'est pas typiquement le genre de chose auquel on pourrait être confronté avec le patron de conception "chaine de responsabilité"
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  4. #4
    Membre Expert
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void f2(/* paramètres */){
        if(test){
            f0();
        }else{
           f3(/* paramètres */);
        }
    }
    ?

  5. #5
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 635
    Par défaut
    Citation Envoyé par therwald Voir le message
    ?
    Oui, bien sur!!!

    J'étais parti sur un return f3() qui aurait été tout à fait juste...

    Mais, en l'absence du return, il faut bel et bien un else
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  6. #6
    Membre Expert
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Je suppose que tout est dans un seul fichier source, naturellement?

    Pourrais-tu poster le fichier entier?
    Tout dans un seul fichier oui.
    Je ne peux pas le poster par contre, désolé.

    @koala01
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void f2(/* paramètres */){
        if(test)
            f0();
        else
            f3(/* paramètres */);
    }
    Devrait normalement être optimisé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void f2(/* paramètres */){
        if(!test)
            f3(/* paramètres */);
    }
    Et il n'y a plus de trace de f0.

    Mais c'est peut être ça avec des fonctions forcées non inline.

  7. #7
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 635
    Par défaut
    Normalement, peut être, si tout se trouve vraiment dans le même fichier et que les deux fonctions sont "suffisamment proches" l'une de l'autre...

    Mais il suffit que f2 et f0 dans l'exemple se trouvent dans deux fichiers distincts (ah, non, c'est pas le cas ) ou, qui sait, d'un réglage particulier en terme d'optimisation, voire, pourquoi pas, d'une partie (f2) écrite en assembleur (et oui, ça arrive parfois) ou (... on peut surement trouver un tas de cas ) pour que l'optimisation n'ait pas lieu
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  8. #8
    Membre éclairé
    Avatar de gb_68
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2006
    Messages
    232
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2006
    Messages : 232
    Par défaut
    Bonjour,

    il y a plusieurs cas où Visual C++ n'est pas capable d'inliner du code. Ceux-ci sont en parti évoqués dans la documentation de
    inline, __inline, __forceinline mais surtout dans celle du warning C4714 où l'on apprend notamment que :
    For example, the compiler will not inline:
    [...]
    • Some functions with copy constructed objects passed by value when -GX/EHs/EHa is on.
    • Functions returning an unwindable object by value when -GX/EHs/EHa is on.
    Soit en gros : si les exceptions C++ sont actives et que la fonction passe par valeur / retourne des objets avec des constructeurs / destructeurs non triviaux (c'est moche au temps des lambdas et make_XXX de perdre l'inline pour cette cause).
    Par exemple le simple code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    std::string foo2()
    {
        return "hello !";
    }
     
    std::string foo1()
    {
        return foo2();
    }
    Produira l'assembleur suivant en release (RVO parfaite mais pas d'inline !)
    Code asm : 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
    std::string foo1()
    {
    00FF12B0  push        ebp  
    00FF12B1  mov         ebp,esp  
    00FF12B3  push        ecx  
    00FF12B4  push        esi  
    00FF12B5  mov         esi,ecx  
    00FF12B7  mov         dword ptr [ebp-4],0  
        return foo2();
    00FF12BE  call        foo2 (0FF1270h)  
    00FF12C3  mov         eax,esi  
    00FF12C5  pop         esi  
    }
    00FF12C6  mov         esp,ebp  
    00FF12C8  pop         ebp  
    00FF12C9  ret
    En désactivant les exceptions, le code est inliné.

  9. #9
    Membre Expert
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Par défaut
    Merci !

    Et un "gros" coût caché des exceptions mis en évidence.

  10. #10
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par Iradrille Voir le message
    Merci !

    Et un "gros" coût caché des exceptions mis en évidence.
    Chez MS. g++, Oracle CC, IBM xlC n'ont aucun probleme a inliner cet exemple (le mieux c'est encore xlC qui donne simplement deux noms au meme code).

  11. #11
    Membre Expert
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Par défaut
    Citation Envoyé par Iradrille Voir le message
    Merci !

    Et un "gros" coût caché des exceptions mis en évidence.
    Dans le cas où tu utilises VC++...

  12. #12
    Membre Expert
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Par défaut
    Dans le cas de VS effectivement.

    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Chez MS. g++, Oracle CC, IBM xlC n'ont aucun probleme a inliner cet exemple (le mieux c'est encore xlC qui donne simplement deux noms au meme code).
    Une ressource est dispo quelque part, montrant les différences de ce genre au niveau des différents compilos ?
    Une liste des choses à faire / éviter en fonctions des compilos parce qu'ils ont du mal avec.

  13. #13
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par Iradrille Voir le message
    Dans le cas de VS effectivement.



    Une ressource est dispo quelque part, montrant les différences de ce genre au niveau des différents compilos ?
    Une liste des choses à faire / éviter en fonctions des compilos parce qu'ils ont du mal avec.
    Pas a ma connaissance. J'ai juste teste avec les compilos que j'avais sous la main (j'ai pas teste avec clang p.e.)

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 09/03/2015, 09h10
  2. lancer une macro en fonction si une cellule est vide ou non
    Par timtof2011 dans le forum Macros et VBA Excel
    Réponses: 6
    Dernier message: 26/11/2011, 14h12
  3. lancer une macro en fonction si une cellule est vide ou non
    Par timtof2011 dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 15/11/2011, 10h01
  4. return array vide et non null
    Par mereyj dans le forum PostgreSQL
    Réponses: 1
    Dernier message: 18/04/2005, 20h25
  5. Fonction vide
    Par vagabon dans le forum Autres éditeurs
    Réponses: 9
    Dernier message: 29/07/2003, 18h23

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