如何检测堆栈溢出点

时间:2009-04-12 18:49:55

标签: c linux gdb stack-overflow callstack

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

程序因信号SIGSEGV,分段故障而终止。 该计划已不复存在。

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

可悲的是,gdb不允许我轻松地使用该程序。

3 个答案:

答案 0 :(得分: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

答案 1 :(得分: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

答案 2 :(得分:4)

当一个程序死于SIGSEGV时,它通常会在Unix上转储核心。你能把这个核心加载到调试器中并检查堆栈的状态吗?