如何在gdb堆栈跟踪充满'??'时调试分段错误?

yve*_*mes 13 c++ linux coredump

我的可执行文件包含符号表 但似乎堆栈跟踪已被覆盖.

如何从该核心获取更多信息?例如,有没有办法检查堆?查看填充堆的对象实例以获取一些线索.无论如何,任何想法都值得赞赏.

roo*_*ook 14

我是一名C++程序员,我遇到过这个问题的次数比我想承认的要多.您的应用程序正在粉碎堆栈中的巨大部分.机会是破坏堆栈的功能也会在返回时崩溃.原因是因为返回地址已被覆盖,这就是GDB的堆栈跟踪混乱的原因.

这就是我调试此问题的方法:

1)逐步通过应用程序直到它崩溃.(查找返回时崩溃的函数).

2)确定函数后,在函数的第一行声明一个变量:

int canary=0;
Run Code Online (Sandbox Code Playgroud)

(它必须是第一行的原因是该值必须位于堆栈的最顶层.这个"canary"将在函数的返回地址之前被覆盖.)

3)在金丝雀上放一个变量值表,通过函数和金丝雀!= 0,然后你发现你的缓冲区溢出了!另一种可能是它为canary!= 0设置变量断点并且只是正常运行程序,这有点容易,但不是所有IDE的支持变量断点.

编辑: 我已经和我办公室的高级程序员交谈,以了解解析内存地址所需的核心转储.找出这些地址的一种方法是查看二进制文件的MAP文件,该文件是人类可读的.以下是使用gcc生成MAP文件的示例:

gcc -o foo -Wl,-Map,foo.map foo.c
Run Code Online (Sandbox Code Playgroud)

这是一个难题,但仍然很难获得崩溃的函数的地址.如果您在现代平台上运行此应用程序,那么ASLR可能会使核心转储中的地址无效.ASLR的一些实现将随机化二进制的函数地址,这使得核心转储绝对毫无价值.


ded*_*ihp 5

  1. 你必须使用一些调试器来检测,valgrind 是可以的
  2. 当您编译代码时,请确保添加 -Wall 选项,它使编译器会告诉您是否有错误(确保您的代码中有任何警告)。

例如:gcc -Wall -g -c -o oke.o oke.c
3. 确保您还有 -g 选项来生成调试信息。您可以使用一些宏调用调试信息。以下宏对我非常有用:

__LINE__ : 告诉你线路

__FILE__ : 告诉你源文件

__func__ : 告诉你函数

  1. 我认为使用调试器是不够的,您应该习惯于最大限度地提高编译器的能力。

希望这会有所帮助