导致SIGSEGV的原因

时间:2009-10-14 05:20:15

标签: sigsegv

我需要知道分段错误的根本原因(SIGSEGV),以及如何处理它。

7 个答案:

答案 0 :(得分:46)

Wikipedia有答案,还有其他一些来源。

段错误基本上意味着你用指针做了坏事。这可能是一个段错误:

char *c = NULL;
...
*c; // dereferencing a NULL pointer

或者这个:

char *c = "Hello";
...
c[10] = 'z'; // out of bounds, or in this case, writing into read-only memory

或许这个:

char *c = new char[10];
...
delete [] c;
...
c[2] = 'z'; // accessing freed memory

每种情况都有相同的基本原则 - 你正在做一些不属于你的记忆。

答案 1 :(得分:12)

分段错误有多种原因,但从根本上说,您正在错误地访问内存。这可能是由于解除引用空指针,或者尝试修改只读内存,或者使用指向未映射到进程内存空间的某个地方(这可能意味着您尝试使用数字作为指针) ,或者你将指针递增太多)。在某些机器上,通过指针进行错位访问也可能导致问题 - 如果你有一个奇数地址并尝试从中读取偶数个字节,例如(可以生成SIGBUS)。 / p>

答案 2 :(得分:6)

使用无效/空指针?超越数组的范围?如果没有任何示例代码,很难具体。

基本上,您正在尝试访问不属于您的程序的内存,因此操作系统会将其杀死。

答案 3 :(得分:4)

以下是SIGSEGV的一个例子。

root@pierr-desktop:/opt/playGround# cat test.c
int main()
{
     int * p ;
     * p = 0x1234;
     return 0 ;
}
root@pierr-desktop:/opt/playGround# g++ -o test test.c  
root@pierr-desktop:/opt/playGround# ./test 
Segmentation fault

这是detail

  

如何处理?

  1. 尽可能避免使用它 第一名。

    防御性编程:使用assert(),检查NULL指针,检查缓冲区溢出。

    使用静态分析工具检查代码。

    使用-Werror -Wall编译代码。

    是否有人审核您的代码。

  2. 实际发生的时候。

    仔细检查您的代码。

    检查自上次代码成功运行以来没有崩溃的情况。

    希望gdb会给你一个调用堆栈,以便你知道崩溃的发生地点。


  3. 编辑:抱歉匆忙。它应该是*p = 0x1234;而不是p = 0x1234;

答案 4 :(得分:1)

SigSegV表示内存访问冲突的信号,试图从您的进程无法访问的内存区域读取或写入。这些不是C或C ++例外,因此您无法捕获信号。确实可以编写一个忽略问题的信号处理程序,并允许在不确定状态下继续执行不稳定的程序,但这显然是一个非常糟糕的主意。

大多数情况下,这是由于程序中的错误所致。给出的内存地址可以帮助调试问题所在(如果接近零,则可能是空指针取消引用;如果地址类似于0xadcedfe,则表示有意保护或调试检查等)

“捕获”信号的一种方法是在一个单独的子进程中运行您的东西,然后该子进程可以突然终止而无需关闭主进程。找出根本原因并加以解决显然比这种解决方法更可取。

答案 5 :(得分:0)

当您访问程序未声明的内存时,出现分段错误。您可以通过指针(即通过内存地址)执行此操作。或这也可能是由于堆栈溢出造成的,例如:

void rec_func() {int q = 5; rec_func();}

int main() {rec_func();}

此调用将继续消耗堆栈内存,直到它完全填满,从而最终发生堆栈溢出。 注意:在某些竞争性问题中,它可能不可见,因为它首先会导致timeouterror,但对于那些没有发生超时的问题,很难找出sigsemv。

答案 6 :(得分:0)

最初的原因也可能是内存不足。