代码之家  ›  专栏  ›  技术社区  ›  Manuel

如何检测堆栈溢出点

  •  10
  • Manuel  · 技术社区  · 15 年前

    我的C程序有以下问题:某个地方是堆栈溢出。尽管编译时没有进行优化和使用调试器符号,但程序还是使用此输出退出(在Linux上的gdb内部或外部):

    程序以信号SIGSEGV终止,分段故障。 程序不再存在。

    唯一可以检测到这实际上是堆栈溢出的方法是通过valgrind运行程序。我有没有办法强迫操作系统转储一个调用堆栈跟踪来帮助我定位问题?

    遗憾的是,gdb也不允许我轻松地进入程序。

    3 回复  |  直到 15 年前
        1
  •  17
  •   David Rodríguez - dribeas    15 年前

    如果允许系统转储核心文件,可以使用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,这取决于当前系统中内核的默认配置,但可以使用(以根目录或sudo运行)进行控制:

    $ sysctl kernel.core_uses_pid=1
    
        2
  •  8
  •   Bastien Léonard    15 年前

    有了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

        3
  •  4
  •   Arkadiy    15 年前

    当一个程序使用sigsegv死机时,它通常将内核转储到Unix上。你能把这个核心加载到调试器中并检查堆栈的状态吗?