SIGABRT和SIGSEGV有什么区别

What is the difference between SIGABRT and SIGSEGV

本文关键字:什么 区别 SIGSEGV SIGABRT      更新时间:2023-10-16

我用下面的两段代码犯了核心转储错误:

//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而被核心转储。

你能说出有什么区别吗?

SIGABRT 被显式检测,并通过检测到第二次删除无效的删除实现发出信号。它通过调用中止函数启动

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

见 https://en.cppreference.com/w/c/program/SIG_types

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

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

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

这两个例子都是未定义的行为,这意味着根据C ++,编译器(和系统)可以做任何它想做的事情。

  • 在情况 1 中,可能会检查指针的双重删除,因此发出SIGABRT信号。 SIGABRT 表示异常终止条件,例如由 abort() 启动。
  • 在情况 2 中,系统会检测到您对已删除指针的尊重,并且创建SIGSEGV信号。 SIGSEGV 表示内存访问无效(分段错误)

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