SIGABRT和SIGSEGV有什么区别

时间:2019-01-22 07:34:23

标签: c++ linux signals coredump

我使用上面的两段代码使核心转储错误:

//test.cpp
int main()
{
    int *p = new int;
    *p = 100;
    delete p;
    delete p;
    return 0;
}

//test2.cpp
int main()
{
    int *p = new int;
    *p = 100;
    delete p;
    *p = 111;
    std::cout<<*p<<std::endl;
    return 0;
}

Gdb告诉我,由于信号SIGABRT,第一部分代码被核心转储,而由于信号SIGSEGV,第二部分代码被核心转储。

您能告诉我们有什么区别吗?

3 个答案:

答案 0 :(得分:3)

删除的实现明确检测并通知了SIGABRT,检测到第二个删除的无效性。通过调用 abort 函数

启动

SIGSEGV与众不同,它正在进行中,而不是像以前的库中的检查所检测到的那样,而是通过操作系统的内存管理启动的

请参阅https://en.cppreference.com/w/c/program/SIG_types

答案 1 :(得分:2)

这两个示例都是未定义的行为,这意味着根据c ++,编译器(和系统)可以执行所需的任何操作。

  • 在情况1中,可能需要检查指针的两次删除,因此发出SIGABRT信号。 SIGABRT表示异常终止条件,例如由abort()启动。
  • 在第2种情况下,系统检测到您对删除的指针的引用,并且 创建一个SIGSEGV信号。 SIGSEGV表示无效的内存访问(分段错误)

但是两者仍然是UB,因此这只是当前编译器/操作系统/系统的功能。从错误here的定义中可以明显看出错误之间的区别。一种是中止,通常由编译器或编码器生成。原因之一是无效的内存访问,通常是由操作系统或硬件发出的信号。

答案 2 :(得分:2)

两次删除指针是未定义的行为,这意味着任何事情都可能发生。在这种情况下,会导致发出SIGABRT信号。

访问不属于程序的内存也是未定义的行为,在这种情况下会导致分段错误并发出SIGSEGV

  • SIGABRT表示程序本身检测到并通过调用abort报告的错误。
  • SIGSEGV表示对有效内存的无效访问。