是什么导致了 SIGSEGV?

发布于 2024-08-07 04:29:15 字数 36 浏览 1 评论 0原文

分段错误 (SIGSEGV) 的根本原因是什么?如何处理?

What is the root cause of the segmentation fault (SIGSEGV), and how to handle it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

场罚期间 2024-08-14 04:29:15

维基百科 以及许多其他来源提供了答案。

段错误基本上意味着您对指针做了一些不好的事情。这可能是一个段错误:

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

在每种情况下都有相同的基本原则 - 你正在用不属于你的内存做一些事情。

Wikipedia has the answer, along with a number of other sources.

A segfault basically means you did something bad with pointers. This is probably a segfault:

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

Or this:

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

Or maybe this:

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

Same basic principle in each case - you're doing something with memory that isn't yours.

苦妄 2024-08-14 04:29:15

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

There are various causes of segmentation faults, but fundamentally, you are accessing memory incorrectly. This could be caused by dereferencing a null pointer, or by trying to modify readonly memory, or by using a pointer to somewhere that is not mapped into the memory space of your process (that probably means you are trying to use a number as a pointer, or you incremented a pointer too far). On some machines, it is possible for a misaligned access via a pointer to cause the problem too - if you have an odd address and try to read an even number of bytes from it, for example (that can generate SIGBUS, instead).

歌入人心 2024-08-14 04:29:15

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

大多数时候这是因为程序中的错误。给出的内存地址可以帮助调试问题所在(如果它接近零,那么它可能是空指针取消引用,如果地址类似于 0xadcedfe 那么它是有意的保护或调试检查等)

“捕获”问题的一种方法信号是在一个单独的子进程中运行您的东西,然后该子进程可以突然终止,而不会导致您的主进程随之关闭。找到根本原因并解决它显然比这样的解决方法更可取。

SigSegV means a signal for memory access violation, trying to read or write from/to a memory area that your process does not have access to. These are not C or C++ exceptions and you can’t catch signals. It’s possible indeed to write a signal handler that ignores the problem and allows continued execution of your unstable program in undefined state, but it should be obvious that this is a very bad idea.

Most of the time this is because of a bug in the program. The memory address given can help debug what’s the problem (if it’s close to zero then it’s likely a null pointer dereference, if the address is something like 0xadcedfe then it’s intentional safeguard or a debug check, etc.)

One way of “catching” the signal is to run your stuff in a separate child process that can then abruptly terminate without taking your main process down with it. Finding the root cause and fixing it is obviously preferred over workarounds like this.

溺孤伤于心 2024-08-14 04:29:15

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

本质上,您试图访问不属于您的程序的内存,因此操作系统会杀死它。

using an invalid/null pointer? Overrunning the bounds of an array? Kindof hard to be specific without any sample code.

Essentially, you are attempting to access memory that doesn't belong to your program, so the OS kills it.

爱她像谁 2024-08-14 04:29:15

这是 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

这是详细信息

如何处理?

  1. 尽量避免
    第一名。

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

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

    使用 -Werror -Wall 编译代码。

    让人检查你的代码。

  2. 当这件事真正发生时。

    仔细检查你的代码。

    检查自上次代码成功运行且没有崩溃以来您进行了哪些更改。

    希望 gdb 能给您一个调用堆栈,以便您知道崩溃发生在哪里。


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

Here is an example of 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

And here is the detail.

How to handle it?

  1. Avoid it as much as possible in the
    first place.

    Program defensively: use assert(), check for NULL pointer , check for buffer overflow.

    Use static analysis tools to examine your code.

    compile your code with -Werror -Wall.

    Has somebody review your code.

  2. When that actually happened.

    Examine you code carefully.

    Check what you have changed since the last time you code run successfully without crash.

    Hopefully, gdb will give you a call stack so that you know where the crash happened.


EDIT : sorry for a rush. It should be *p = 0x1234; instead of p = 0x1234;

め可乐爱微笑 2024-08-14 04:29:15

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

The initial source cause can also be an out of memory.

几味少女 2024-08-14 04:29:15

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

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

int main() {rec_func();}

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

Segmentation fault arrives when you access memory which is not declared by the program. You can do this through pointers i.e through memory addresses. Or this may also be due to stackoverflow for example:

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

int main() {rec_func();}

This call will keep on consuming stack memory until it's completely filled and thus finally stackoverflow happens.
Note: it might not be visible in some competitive questions as it leads to timeouterror first but for those in which timeout doesn't happens its a hard time figuring out SIGSEGV.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文