Wie kann man quellcodemaßig(rolf) checken ob eine Methode tatsächlich inlinde wurde?



  • Hallo zusammen,
    es gibt mehrere Rumors darüber ob und wie die verschiedene c/c++ Kompiler die Methode freiwillig zum Inline machen bzw. auf eine die inline Anweisung verzichten 😃
    Kenn vllt jemand ein kurzer quellcode- trick um beim Laufzeit zu testen ob eine Methode inlined wurde oder per Pointer zu Speicherbereich aufgerufen wurde?

    Danke für Antworten.


  • Mod

    Muss es ausgerechnet zur Laufzeit sein?



  • Gewünscht, aber nicht zwingend: ich würde mich auch auf Compilezeit oder Macros- checks interessieren.


  • Mod

    o4kareg schrieb:

    Gewünscht, aber nicht zwingend: ich würde mich auch auf Compilezeit oder Macros- checks interessieren.

    Dann musst du in deinem Compilerhandbuch gucken. Manche Compiler (z.B. der von Intel) bieten die Option, ausführlich über gemachte Optimierungen zu berichten.

    Eine allgemeine Methode wäre, sich nach dem Compilieren die erzeugte Datei anzusehen. Oft kann man sich auch direkt vom Compiler das Assembly ausgeben lassen (wieder: Compilerhandbuch). Oftmals lesbarer ist jedoch ein Disassembler (zumindest wenn du Debugsymbole eincompiliert hast). Z.B. unter Linux, mit GCC und objdump:
    test.c:

    #include <stdio.h>
    
    int add(int a, int b)
    {
      return a + b;
    }
    
    int main()
    {
      int a,b;
      scanf("%i %i", &a, &b);
      printf("%i\n", add(a,b));
    }
    
    [b]$> [/b]gcc -g -O0 test.c
    [b]$> [/b]objdump --demangle --line-numbers --debugging --disassemble-all --source --all-header ./a.out #Hier nur relevanter Teil der Ausgabe gezeigt:
    int main()
    {
      400550:       55                      push   %rbp
      400551:       48 89 e5                mov    %rsp,%rbp
      400554:       48 83 ec 10             sub    $0x10,%rsp
    /home/zensiert/src/test/test.c:11
      int a,b;
      scanf("%i %i", &a, &b);
      400558:       48 8d 55 f8             lea    -0x8(%rbp),%rdx
      40055c:       48 8d 45 fc             lea    -0x4(%rbp),%rax
      400560:       48 89 c6                mov    %rax,%rsi
      400563:       bf 4c 06 40 00          mov    $0x40064c,%edi
      400568:       b8 00 00 00 00          mov    $0x0,%eax
      40056d:       e8 ae fe ff ff          callq  400420 <__isoc99_scanf@plt>
    /home/zensiert/src/test/test.c:12
      printf("%i\n", add(a,b));
      400572:       8b 55 f8                mov    -0x8(%rbp),%edx
      400575:       8b 45 fc                mov    -0x4(%rbp),%eax
      400578:       89 d6                   mov    %edx,%esi
      40057a:       89 c7                   mov    %eax,%edi
      40057c:       e8 bb ff ff ff          callq  40053c <add>
      400581:       89 c6                   mov    %eax,%esi
      400583:       bf 52 06 40 00          mov    $0x400652,%edi
      400588:       b8 00 00 00 00          mov    $0x0,%eax
      40058d:       e8 6e fe ff ff          callq  400400 <printf@plt>
    /home/zensiert/src/test/test.c:13
    }
    
    [b]$> [/b]gcc -g -O3 test.c
    [b]$> [/b]objdump --demangle --line-numbers --debugging --disassemble-all --source --all-header ./a.out #Hier nur relevanter Teil der Ausgabe gezeigt:
    int main()
    {
      400430:       48 83 ec 18             sub    $0x18,%rsp
    /home/zensiert/src/test/test.c:11
      int a,b;
      scanf("%i %i", &a, &b);
      400434:       bf 2c 06 40 00          mov    $0x40062c,%edi
      400439:       31 c0                   xor    %eax,%eax
      40043b:       48 8d 54 24 0c          lea    0xc(%rsp),%rdx
      400440:       48 8d 74 24 08          lea    0x8(%rsp),%rsi
      400445:       e8 d6 ff ff ff          callq  400420 <__isoc99_scanf@plt>
    add():
    /home/zensiert/src/test/test.c:5
    #include <stdio.h>
    
    int add(int a, int b)
    {
      return a + b;
      40044a:       8b 74 24 0c             mov    0xc(%rsp),%esi
      40044e:       03 74 24 08             add    0x8(%rsp),%esi
    main():
    /home/zensiert/src/test/test.c:12
    
    int main()
    {
      int a,b;
      scanf("%i %i", &a, &b);
      printf("%i\n", add(a,b));
      400452:       bf 32 06 40 00          mov    $0x400632,%edi
      400457:       31 c0                   xor    %eax,%eax
      400459:       e8 a2 ff ff ff          callq  400400 <printf@plt>
    /home/zensiert/src/test/test.c:13
    }
    

    Man sieht selbst ohne tiefergehende Assemblerkenntnisse, dass die funktion bei der unoptimierten Variante explizit aufgerufen wird, während sie bei der zweiten Variante in den Code der main-Funktion eingebaut wurde.



  • Dieser Thread wurde von Moderator/in SeppJ aus dem Forum C (C89 und C99) in das Forum Rund um die Programmierung verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • MSVC hat __forceinline, da kommt dann laut MSDN ne Level 1 Warning wenn die Funktion nicht geinlined werden konnte.

    Wobei der Compiler bei __forceinline dann auf Teufel komm raus versucht die Funktion inline zu machen, was also überhaupt nicht dem verhalten ohne __forceinline entspricht.


Anmelden zum Antworten