为什么gdb显示两个不同的回报?

时间:2010-05-10 12:03:34

标签: c++ gdb

上周我调试了一段代码并出现了一个奇怪的情况:gdb传递了两个不同的return子句。我做了一个简单的例子说明了这种情况:

#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

3 个答案:

答案 0 :(得分:4)

我怀疑你看到了这个功能结局。你的两个字符串都有析构函数,它们在返回时被隐式调用。查看反汇编说的确定内容,但我怀疑两个返回语句都映射到以下内容:

stash return_value;
goto epilogue;

并相应地:

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

结语似乎来自第15行,作为g ++如何进行行编号的副作用 - 一种相当简单的格式,实际上只是“地址X来自行号Y”形式的标签列表 - 所以它是报告15为最接近的匹配。在这种情况下令人困惑,但在很多时候都要纠正。

答案 1 :(得分:3)

可能是因为程序计数器寄存器通过最佳映射到最终返回的指令,即函数的退出序列。实际返回值可能保存在寄存器中,因此第一个return只加载正确的值并跳转到函数的末尾,然后该地址被“反向映射”到源代码行。最后return

答案 2 :(得分:2)

您没有说,但如果您使用完全的优化进行编译,那么您将在gdb中看到这种行为。你看到第一行设置返回值,然后它跳转到实际的返回指令但是在C ++中你会看到整个事情,包括返回值。