2010-05-10 4 views
7

Letzte Woche war ich ein Debugging eines Codes und eine seltsame Situation kam auf: gdb durchläuft zwei verschiedene Rückgabeklauseln. Ich habe ein einfaches Beispiel, das die Situation zeigt:Warum zeigt gdb zwei verschiedene Renditen?

#include <iostream> 

using namespace std; 

int test() { 

    string a = "asd"; 
    string b = "asd"; 

    while (true) { 
     if (a == b) { 
      return 0; 
     } 
    } 
    return -1; 
} 

int main() { 
    int result = test(); 
    cout << "result: " << result << endl; 
} 

Beim Debuggen den Code ich habe:

(gdb) b main 
Breakpoint 1 at 0x1d4c: file example.cpp, line 19. 
(gdb) r 
Starting program: /Users/yuppienet/temp/a.out 
Reading symbols for shared libraries +++. done 

Breakpoint 1, main() at example.cpp:19 
19   int result = test(); 
(gdb) s 
test() at example.cpp:7 
7   string a = "asd"; 
(gdb) n 
8   string b = "asd"; 
(gdb) n 
11    if (a == b) { 
(gdb) n 
12     return 0; 
(gdb) n 
15   return -1; 
(gdb) n 
16  } 
(gdb) n 
main() at example.cpp:20 
20   cout << "result: " << result << endl; 
(gdb) n 
result: 0 
21  } 
(gdb) n 
0x00001ab2 in start() 

ich, dass auch bemerkt, wenn gdb Linie zeigt 15, ist der Rückgabewert 0 (finish Befehl bestätigt dies auch).

Die Frage ist also: Warum zeigt GDB Zeile 15: return -1, auch wenn die Funktion diesen Wert nicht wirklich zurückgibt?

Danke!

Edit: Ich habe vergessen, dass ich mit der folgenden Zeile zusammengestellt zu erwähnen:

g++ -Wall -pedantic -g -pg example.cpp 

Antwort

4

Ich vermute, Sie sehen die Funktion Epilog. Ihre zwei Strings haben Destruktoren, die bei der Rückgabe implizit aufgerufen werden. Lesen Sie, was die Demontage sicher sein, sagt, aber ich vermute, dass beide return-Anweisungen zuordnen, etwas entlang der Linien von:

stash return_value; 
goto epilogue; 

und entsprechend:

epilogue: 
    destroy a; // on the stack, so destructor will be called 
    destroy b; 
    really_return(stashed value); 

Der Epilog erscheint von Zeile zu kommen 15 als Nebeneffekt der Zeilennummerierung von g ++ - ein ziemlich einfaches Format, eigentlich nur eine Liste von Tags der Form "Adresse X kommt von Zeilennummer Y" - also meldet sie 15 als nächstliegende Übereinstimmung. Verwirrend in diesem Fall, aber korrigieren Sie die meiste Zeit.

+3

+1 Dies sieht aus, die Antwort zu sein - wenn Sie a und b zu ints ändern, sehen Sie nicht die Rückkehr -1 –

3

Wahrscheinlich, weil das Programmzählerregister durchläuft die Anweisungen, die beste Karte, um die endgültige Rückkehr, das heißt die Funktion der Exit-Sequenz. Der tatsächliche Rückgabewert wird wahrscheinlich in einem Register gehalten, so dass der erste return nur den richtigen Wert lädt und zum Ende der Funktion springt, und dann wird diese Adresse auf die Quellcodezeile des letzten return "rückabgebildet".

2

Sie sagen nicht, aber wenn Sie mit der Optimierung kompiliert haben, ist das genau die Art von Verhalten, das Sie in gdb sehen würden. Sie sehen die erste Zeile, die den Rückgabewert einrichtet, und dann springt er auf die echte Rückgabeanweisung, aber in C++ sehen Sie die gesamte Sache einschließlich des Rückgabewerts.

+0

Eigentlich kompiliert ich mit 'g ++ -Wand -pedantisch -g -pg' – YuppieNetworking