当前位置:  开发笔记 > 后端 > 正文

堆栈溢出的Segfault

如何解决《堆栈溢出的Segfault》经验,为你挑选了3个好方法。

为什么linux内核会在堆栈溢出时生成段错误?当c中的alloca或临时数组的fortran创建溢出时,这会使调试变得非常尴尬.当然,运行时可能会产生更有用的错误.



1> miguel.de.ic..:

您实际上可以使用信号处理程序捕获堆栈溢出的条件.

要做到这一点,你必须做两件事:

使用sigaction为SIGSEGV(segfault)设置信号处理程序,为此设置SO_ONSTACK标志.这指示内核在传递信号时使用备用堆栈.

调用sigaltstack()来设置SIGSEGV的处理程序将使用的备用堆栈.

然后,当您溢出堆栈时,内核将在发送信号之前切换到备用堆栈.进入信号处理程序后,您可以检查导致故障的地址,并确定它是堆栈溢出还是常规故障.



2> paxdiablo..:

"内核"(它实际上不是运行代码的内核,它是CPU)不知道你的代码如何引用它不应该触及的内存.它只知道你试图这样做.

代码:

char *x = alloca(100);
char y = x[150];

当您尝试超出x的范围时,CPU无法真正评估它.

您可以点击完全相同的地址:

char y = *((char*)(0xdeadbeef));

顺便说一下,我不鼓励使用alloca,因为堆栈往往比堆更有限(使用malloc代替).



3> Sargun Dhill..:

堆栈溢出是分段错误.就像你已经打破了你最初分配的内存界限一样.有限大小的堆栈,你已经超过了它.您可以在维基百科上阅读更多相关信息

另外,我过去为项目做过的一件事就是将自己的信号处理程序写入segfault(查看手册页信号(2)).我经常抓住信号并写出"致命错误已经发生"到控制台.我做了一些关于检查点标志和调试的东西.

为了调试段错误,您可以在GDB中运行程序.例如,以下C程序将是段错误:#segfault.c #include #include

int main() 
{
        printf("Starting\n");
        void *foo=malloc(1000);
        memcpy(foo, 0, 100); //this line will segfault
        exit(0);
}

如果我这样编译它:

gcc -g -o segfault segfault.c 

然后像这样运行它:

$ gdb ./segfault
GNU gdb 6.7.1
Copyright (C) 2007 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...
Using host libthread_db library "/lib/libthread_db.so.1".
(gdb) run
Starting program: /tmp/segfault 
Starting

Program received signal SIGSEGV, Segmentation fault.
0x4ea43cbc in memcpy () from /lib/libc.so.6
(gdb) bt
#0  0x4ea43cbc in memcpy () from /lib/libc.so.6
#1  0x080484cb in main () at segfault.c:8
(gdb) 

我从GDB中发现第8行有一个分段错误.当然,有更复杂的方法来处理堆栈溢出和其他内存错误,但这就足够了.

推荐阅读
勤奋的瞌睡猪_715
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有