11

我的 C 程序有以下问题: 某处是堆栈溢出。尽管在没有优化和调试器符号的情况下进行编译,但程序会以以下输出退出(在 Linux 上的 gdb 内部或外部):

程序因信号 SIGSEGV、分段错误而终止。该程序不再存在。

我可以检测到这实际上是堆栈溢出的唯一方法是通过 valgrind 运行程序。有什么办法可以强制操作系统转储调用堆栈跟踪,这将帮助我找到问题?

可悲的是,gdb 也不允许我轻松进入该程序。

4

3 回答 3

17

如果您允许系统转储核心文件,您可以使用 gdb 分析它们:

$ ulimit -c unlimited # bash sentence to allow for infinite sized cores
$ ./stack_overflow
Segmentation fault (core dumped)
$ gdb -c core stack_overflow
gdb> bt
#0  0x0000000000400570 in f ()
#1  0x0000000000400570 in f ()
#2  0x0000000000400570 in f ()
...

有时我看到一个生成错误的核心文件有一个不正确的堆栈跟踪,但在大多数情况下,bt 会产生一堆对同一方法的递归调用。

核心文件可能有一个不同的名称,其中可能包含进程 ID,它取决于当前系统中内核的默认配置,但可以使用(以 root 身份运行或使用 sudo)进行控制:

$ sysctl kernel.core_uses_pid=1
于 2009-04-12T19:32:08.830 回答
8

使用 GCC,您可以尝试以下操作:

-fstack-protector
发出额外的代码来检查缓冲区溢出,例如堆栈粉碎攻击。这是通过将保护变量添加到具有易受攻击对象的函数来完成的。这包括调用 alloca 的函数,以及缓冲区大于 8 字节的函数。进入函数时初始化守卫,然后在函数退出时检查。如果保护检查失败,则会打印一条错误消息并退出程序。

-fstack-protector-all
与 -fstack-protector 类似,只是所有函数都受到保护。

http://gcc.gnu.org/onlinedocs/gcc-4.3.3/gcc/Optimize-Options.html#Optimize-Options

于 2009-04-12T18:54:11.900 回答
4

当一个程序因 SIGSEGV 而死时,它通常会在 Unix 上转储内核。您可以将该内核加载到调试器中并检查堆栈的状态吗?

于 2009-04-12T19:15:42.490 回答