如何解释GDB的回溯(backtrace)信息?

8
0x004069f1 in Space::setPosition (this=0x77733cee, x=-65, y=-49) at space.h:44    
0x00402679 in Checkers::make_move (this=0x28cbb8, move=...) at checkers.cc:351
0x00403fd2 in main_savitch_14::game::make_computer_move (this=0x28cbb8) at game.cc:153
0x00403b70 in main_savitch_14::game::play (this=0x28cbb8) at game.cc:33
0x004015fb in _fu0___ZSt4cout () at checkers.cc:96
0x004042a7 in main () at main.cc:34

你好,我正在为一门课程编写游戏,但是遇到了段错误。卒子被保存在一个二维数组中,所以问题似乎出在了数组的无效x/y位置上。移动是作为字符串传递的,然后会将其转换为整数,因此x和y可能会变成ASCII NULL。我注意到在函数调用make_move中,它说move=...?还有,如何解决段错误的其他快速技巧?我对GDB有点陌生。


首先,你应该使用像std::vector这样的东西,它会在越界时抛出一个易于识别的异常(并且在使用at()时可以避免你管理内存)。其次,你应该能够设置变量监视器来观察x和y的变化,并查找它们何时变得无效,如果确实是这种情况。 - chris
2个回答

10
基本上,回溯是导致崩溃的调用链跟踪。在这种情况下: game::play 调用 game::make_computer_move,后者调用 Checkers::make_move,后者调用 Space::setPosition,第 44 行在文件 space.h 中崩溃。
查看这个回溯,看起来你将 -65-49 传递给了 Space::setPosition,如果它们是无效坐标(看起来很可疑,因为它们是负数),那么你应该查看调用函数,看看它们的值为什么,并进行更正。
我建议在代码中大量使用 assert 来执行合同,几乎任何时候当你可以说“这个参数或变量只能具有满足某些条件的值”时,你都应该断言它的情况。
一个常见的例子是,如果我有一个函数,它接受一个指针(或更可能是智能指针),该指针不允许为 NULL。我会在函数的第一行写上 assert(p);。如果曾经传递了一个 NULL 指针,我会立即知道并进行调查。
最后,在 gdb 中运行应用程序,当它崩溃时。输入 up 来检查调用栈帧并查看变量的内容:(通常可以在控制台上写类似于 print x 的东西)。同样地,如果需要,down 将向下移动调用栈。
至于 SEGFAULT,我建议在 valgrind 中运行应用程序。如果使用调试信息 -g 编译,它通常可以告诉你导致错误的代码行(甚至可以捕获不会立刻崩溃的不幸错误)。

现在唯一的问题是发现它们何时变为(-65,-49)。这就是变量监视器的好处。 - chris
是的,那似乎就是问题所在。我不知道它们何时或如何变成-65、-49,但我想我能做的就是继续寻找。 - user1405177

4

我不能发表评论,但是想为那些最近在寻找变量变成(-65, -49)的问题的人回复一下。如果你遇到段错误,你可以获取核心转储文件。这里是一个非常好的资源,可以确保你设置了gdb以获取核心转储。然后你可以用gdb打开你的核心文件:

gdb -c myCoreFile

然后在您想要进入的函数调用上设置一个断点:
b MyClass::myFunctionCall

然后使用“下一步”或“步进”来浏览代码行:
step

或者

next

当你在代码的某个地方想要评估一个变量时,你可以打印它:
p myVariable 

或者您可以打印所有参数:

info args

我希望这篇文章能够帮助其他需要进行调试的人!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接