首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Segfault堆栈溢出

Segfault堆栈溢出
EN

Stack Overflow用户
提问于 2008-09-17 08:43:48
回答 6查看 4.3K关注 0票数 12

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

EN

回答 6

Stack Overflow用户

发布于 2008-09-17 22:42:34

实际上,您可以使用信号处理程序来捕获堆栈溢出的情况。

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

  • 使用sigaction为SIGSEGV (段错误)设置一个信号处理程序,为此设置SO_ONSTACK标志。这将指示内核在传递信号时使用备用堆栈。
  • 调用sigaltstack()来设置SIGSEGV的处理程序将使用的备用堆栈。

然后,当你溢出堆栈时,内核将在传递信号之前切换到你的备用堆栈。一旦进入信号处理程序,就可以检查导致错误的地址,并确定它是堆栈溢出还是常规错误。

票数 41
EN

Stack Overflow用户

发布于 2008-09-17 08:48:01

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

代码:

代码语言:javascript
复制
char *x = alloca(100);
char y = x[150];

当您试图访问超出x界限的数据时,CPU不能真正评估它。

您可以使用以下命令访问完全相同的地址:

代码语言:javascript
复制
char y = *((char*)(0xdeadbeef));

顺便说一句,我不鼓励使用alloca,因为堆栈往往比堆有更多的限制(使用malloc )。

票数 7
EN

Stack Overflow用户

发布于 2008-09-17 08:55:31

堆栈溢出是分段错误。因为你已经打破了最初分配给你的内存的界限。有限大小的堆栈,而您已超过它。你可以在wikipedia上阅读更多关于它的内容

此外,我过去为项目所做的一件事就是编写我自己的信号处理程序来分割错误(查看手册页signal (2))。我通常会捕捉到这个信号,并在控制台上写下"Fatal error has occured“。我用检查点标志和调试做了一些进一步的工作。

为了调试段错误,你可以在GDB中运行一个程序。例如,下面的C程序将Segfault.c #include #include

代码语言:javascript
复制
int main() 
{
        printf("Starting\n");
        void *foo=malloc(1000);
        memcpy(foo, 0, 100); //this line will segfault
        exit(0);
}

如果我这样编译它:

代码语言:javascript
复制
gcc -g -o segfault segfault.c 

然后像这样运行它:

代码语言:javascript
复制
$ gdb ./segfault
GNU gdb 6.7.1
Copyright (C) 2007 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
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行有一个分段错误。当然,还有更复杂的方法来处理堆栈溢出和其他内存错误,但这就足够了。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/81202

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档