2010-05-10 6 views
7

La scorsa settimana ho eseguito il debug di un codice e si è verificata una strana situazione: gdb passa attraverso due diverse clausole di restituzione. Ho fatto un semplice esempio che illustra la situazione:Perché gdb mostra due diversi ritorni?

#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; 
} 

Quando il debug del codice che ho ottenuto:

(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() 

ho notato che anche se gdb mostra la linea 15, il valore di ritorno è 0 (il comando finish conferma anche questo).

Quindi la domanda è: perché gdb mostra la riga 15: return -1, anche se la funzione non restituisce effettivamente questo valore?

Grazie!

Edit: Ho dimenticato di dire che ho compilato con la seguente riga:

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

risposta

4

Sospetto che tu stia vedendo l'epilogo della funzione. Le tue due stringhe hanno dei distruttori, che vengono implicitamente richiamati. Verificare che cosa lo smontaggio dice di essere sicuro, ma ho il sospetto che entrambe le dichiarazioni di ritorno sono mappatura per qualcosa sulla falsariga di:

stash return_value; 
goto epilogue; 

e corrispondentemente:

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

L'epilogo sembra provenire dalla linea 15 come effetto collaterale di come g ++ fa la numerazione delle righe - un formato abbastanza semplice, in realtà solo una lista di tag del modulo "indirizzo X deriva dalla linea numero Y" - e quindi riporta 15 come la corrispondenza più vicina. Confondere in questo caso, ma correggere un sacco di tempo.

+3

+1 Questa sembra essere la risposta - se si cambia a e b per essere ints, non si vede il ritorno -1 –

3

Probabilmente perché il registro contatore di programma passa attraverso le istruzioni che meglio mappa per il ritorno finale, vale a dire la sequenza l'uscita della funzione. Il valore di ritorno effettivo è probabilmente conservato in un registro, quindi il primo return carica il valore corretto e salta alla fine della funzione, quindi tale indirizzo viene "mappato indietro" alla riga del codice sorgente dell'ultimo return.

2

Non si dice, ma se si è compilato con ottimizzazione è esattamente il tipo di comportamento che si vedrebbe in gdb. Si vede la prima riga che imposta il valore di ritorno, quindi salta all'istruzione di ritorno reale ma in C++ si vede l'intera cosa incluso il valore di ritorno.

+0

In realtà ho compilato 'g ++ -Wall -pedantic -g -pg' – YuppieNetworking

Problemi correlati