为什么linux内核会在堆栈溢出时生成segfault?当c或fortran中的alloca创建临时数组溢出时,这会使调试变得非常笨拙。当然,运行时可能会产生更有用的错误。
发布于 2008-09-17 22:42:34
实际上,您可以使用信号处理程序来捕获堆栈溢出的情况。
要做到这一点,您必须做两件事:
然后,当你溢出堆栈时,内核将在传递信号之前切换到你的备用堆栈。一旦进入信号处理程序,就可以检查导致错误的地址,并确定它是堆栈溢出还是常规错误。
发布于 2008-09-17 08:48:01
“内核”(实际上不是运行你的代码的内核,它是CPU)不知道你的代码是如何引用它不应该触及的内存的。它只知道你试图这么做。
代码:
char *x = alloca(100);
char y = x[150];当您试图访问超出x界限的数据时,CPU不能真正评估它。
您可以使用以下命令访问完全相同的地址:
char y = *((char*)(0xdeadbeef));顺便说一句,我不鼓励使用alloca,因为堆栈往往比堆有更多的限制(使用malloc )。
发布于 2008-09-17 08:55:31
堆栈溢出是分段错误。因为你已经打破了最初分配给你的内存的界限。有限大小的堆栈,而您已超过它。你可以在wikipedia上阅读更多关于它的内容
此外,我过去为项目所做的一件事就是编写我自己的信号处理程序来分割错误(查看手册页signal (2))。我通常会捕捉到这个信号,并在控制台上写下"Fatal error has occured“。我用检查点标志和调试做了一些进一步的工作。
为了调试段错误,你可以在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 <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行有一个分段错误。当然,还有更复杂的方法来处理堆栈溢出和其他内存错误,但这就足够了。
https://stackoverflow.com/questions/81202
复制相似问题