2010-05-10 53 views
7

上週我是一個調試代碼,出現了一個奇怪的情況:gdb通過兩個不同的return子句。我做了一個簡單的例子,示出了情況:爲什麼gdb顯示兩個不同的回報?

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

當調試我得到的代碼:

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

我指出,即使GDB示出了線15,返回值是0(finish命令也證實了這一點)。

所以問題是:爲什麼gdb顯示第15行:return -1,即使函數沒有真的返回這個值?

謝謝!

編輯: 我忘了提,我有以下行編譯:

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

回答

4

我懷疑你看到函數epilogue。你的兩個字符串具有析構函數,它們在返回時被隱式調用。退房拆卸所說的話是肯定的,但我懷疑,這兩個return語句沿的線條映射到的東西:

stash return_value; 
goto epilogue; 

,並相應:

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

的結尾似乎來自線15作爲g ++如何進行行編號的一個副作用 - 一個相當簡單的格式,實際上只是一個表格「address X來自行號Y」的標籤列表 - 所以它報告15是最接近的匹配。在這種情況下混淆,但糾正了很多時間。

+3

+1這看起來就是答案 - 如果你改變a和b爲整數,你不會看到返回-1 – 2010-05-10 12:34:34

3

大概是因爲程序計數器寄存器通過指令最好映射到最後的回報,即函數的退出序列。實際的返回值可能保存在一個寄存器中,因此第一個return只加載正確的值並跳轉到該函數的末尾,然後該地址被「映射」到最終的return的源代碼行。

2

你不說,但如果你編譯的優化是剛好你會在gdb中看到的那種行爲。您會看到第一行設置返回值,然後跳轉到真正的返回指令,但在C++中,您會看到包括返回值在內的整個事件。

+0

其實我用'g ++ -Wall -pedantic -g -pg'編譯 – YuppieNetworking 2010-05-10 12:13:29