GDB回溯未显示正确信息

4
我正在学习在我的Mac上使用gdb进行调试,当我发现一个分段错误时,我想要利用它来学习。我使用的是homebrew提供的gdb 8.0.1和gcc 7.2.0,我使用-ggdb编译,并通过gdb -ex run ./main直接从我的makefile中运行gdb。
我打开游戏,打开其中的菜单,在试图关闭它时,它崩溃了,因为我在WindowsObject.cpp中执行了以下操作:
WindowObject_CraftingGrid::~WindowObject_CraftingGrid(){
   for (unsigned i = 0; i < gridSlots_.size(); i++) {
      for (unsigned j = 0; j < gridSlots_[0].size(); i++) { //i++ instead of j++, this leads to the crash
         delete gridSlots_[i][j];
      }
   }
}

Gdb 说:

(gdb) bt
#0  0x0000000100023a80 in WindowObject_Image::Draw (this=0x300000000) at src/WindowObjects.cpp:620
#1  0x0000000100023ae2 in WindowObject_Image::setImage (this=0x100a9e980, img=0x0) at src/WindowObjects.cpp:629
#2  0x000000010001d5f7 in WindowMain::AddSection (this=0x100a04ce0, n=28672) at src/Window.cpp:263
#3  0x0000000100033765 in LoadLibrary () at src/main.cpp:781
#4  0x0000000100030b25 in DrawGUI () at src/main.cpp:465
#5  0x0000000100031534 in DrawGUI () at src/main.cpp:501
#6  0x00000001006eae27 in ?? ()
#7  0x0000700001875ef0 in ?? ()
#8  0x00007fff40b796d8 in ?? ()
#9  0x0000000000000000 in ?? ()

这是完全错误的做法,因为它无法指向正确的对象和行,对于解决缺陷没有任何有用的帮助。

我在 Windows 机器上通过 Visual Studio 发现了这个 bug,因为那里的调用堆栈非常清晰:

project.exe!std::vector<std::vector>WindowObjects_Slot * //Other stuff
project.exe!WindowObject_CraftingGrid::~WindowObject_CraftingGrid() Line 348
project.exe!WindowMain::~WindowMain() Line 234
project.exe!KeyPressed(int KeyCode) Line 566
project.exe!gameloop() Line 181
project.exe!main(int argc, char ** argv) Line 321)

1
我怀疑 MSVC 在调试构建中对 std::vector 进行了仪器化,以便通过抛出异常提前失败。也许使用 gdb 调试的实例没有使用相同的陷阱进行编译?请分享第一个实例构建时使用的命令行。 - wally
1
通常,段错误比实际导致它们的问题出现得晚得多。将无效值分配给指针不会崩溃程序,尽管这是实际的错误;解引用指针会导致崩溃,但它可能会在任意时间后发生。 - Daniel H
抱歉,我不知道你所说的“同样的陷阱”是什么意思... 无论如何,在这两台机器上,代码完全相同,但在Windows上我使用Visual Studio,在Mac上我使用Terminal+Makefile+GCC+GDB进行构建,因此我猜可执行文件的两个版本之间存在差异,但主要问题是为什么GDB回溯会输出如此奇怪的信息... - elkiwy
1
我猜@rex的意思是Windows中的“vector”代码在调试模式下有检查是否发生了无效操作。使用您所用的编译标志,GCC则显然没有这些检查,因此稍后会捕获该问题。请问makefile中调用GCC的那一行是什么? - Daniel H
这是在Mac上制作过程的确切输出。|| gcc-7 -Wall -ggdb -std=c++11 -D_GLIBCXX_USE_CXX11_ABI=0 -c -o obj/Block.o src/Block.cpp || ***其他.cpp文件编译*** || gcc-7 -o main ***所有.o文件*** pkg-config --cflags --libs ***所有的allegro库*** -I/usr/local/Boost/Builded/include/ /usr/local/Boost/Builded/lib/libboost_serialization-libstdc++.a /usr/local/Boost/Builded/lib/libboost_filesystem-libstdc++.a /usr/local/Boost/Builded/lib/libboost_system-libstdc++.a /usr/local/Cellar/gcc/7.2.0/lib/gcc/7/libstdc++.a - elkiwy
1个回答

5

这是完全错误的

不,不是这样的:在这个平台上,这是你的应用程序实际崩溃的地方。

因为它没有提供任何有用的信息来解决错误

你有一个堆破坏错误。堆破坏错误就是这样的:在堆破坏之后的某个时间,你的应用程序可能会在任意位置崩溃。

此外,堆栈跟踪并不无用:它告诉你 this == 0x300000000,这不是 this 的合理值,因此你正在查看某种堆破坏。

有许多方法来调试类似的问题:其中包括 调试 mallocAddress SanitizerValgrind

使用-D_GLIBCXX_DEBUG编译选项可以启用GCC STL中的调试模式,并且很可能会直接指出错误。

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