什么时候进程得到SIGABRT(信号6)?

什么情况下,一个进程得到一个SIGABRT在C + +? 这个信号是否始终来自过程中,还是可以将这个信号从一个过程发送到另一个过程?

有没有办法确定哪个进程发送这个信号?

abort()向调用进程发送SIGABRT信号,这就是abort()基本工作的方式。

通常通过库函数调用abort()来检测内部错误或严重破坏的约束。 例如,如果malloc()的内部结构被堆溢出损坏,它将调用abort()

您可以使用kill(2)接口将任何信号发送到任何进程:

kill -SIGABRT 30823

30823是我开始的dash过程,所以我可以很容易地find我想杀死的过程。

 $ /bin/dash $ Aborted 

Aborted输出显然是dash如何报告一个SIGABRT。

它可以使用kill(2)直接发送到任何进程,或者进程可以通过assert(3)abort(3)raise(3)发送信号给自己。

SIGABRT通常由libc和其他库在出现严重错误时中止程序。 例如,如果检测到双免费或其他堆损坏,glibc会发送一个SIGABRT

另外,大多数“ assert ”的实现在断言失败的情况下使用SIGABRT

此外, SIGABRT可以像任何其他信号一样从其他任何进程发送。 当然,发送过程需要以相同的用户或根目录运行。

当内存分配出现问题时,通常会发生这种情况。

当我的程序试图分配负数大小的数组时,它发生在我身上。

在c ++的情况下还有另一个简单的原因。

 std::thread::~thread{ if((joinable ()) std::terminate (); } 

即线程的范围结束,但你忘了打电话

 thread::join(); 

要么

 thread::detach(); 

在调用abort() (然后触发SIGABRT )之前,GNU libc将把关于某些致命条件的信息打印到/dev/tty ,但是如果您将程序作为服务运行,或者不是在真正的terminal窗口中运行,则这些消息可能会迷路,因为没有tty来显示消息。

看到我的文章redirectlibc写入stderr而不是/ dev / tty:

捕获libc错误消息,从/ dev / ttyredirect

一个案例,当过程从自己得到SIGABRT:Hrvoje提到一个隐藏的纯虚拟从ctor调用产生一个中止,我重新创build一个这样的例子。 在这里,当d被构造时,它首先调用它的基类A ctor,并把指针传给它自己。 在表被填充有效指针之前,A ctor调用纯虚方法,因为d还没有被构造。

 #include<iostream> using namespace std; class A { public: A(A *pa){pa->f();} virtual void f()=0; }; class D : public A { public: D():A(this){} virtual void f() {cout<<"D::f\n";} }; int main(){ D d; A *pa = &d; pa->f(); return 0; } 

编译:g ++ -o aa aa.cpp

ulimit -c无限制

运行:./aa

 pure virtual method called terminate called without an active exception Aborted (core dumped) 

现在让我们快速看到核心文件,并validationSIGABRT的确被称为:

 gdb aa core 

见regs:

 ir rdx 0x6 6 rsi 0x69a 1690 rdi 0x69a 1690 rip 0x7feae3170c37 

检查代码:

disas 0x7feae3170c37

 mov $0xea,%eax = 234 <- this is the kill syscall, sends signal to process syscall <----- 

http://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/

234 sys_tgkill pid_t tgid pid_t pid int sig = 6 = SIGABRT

🙂

在我的情况下,这是由于在一个数组中的索引等于数组的长度的input。

 string x[5]; for(int i=1; i<=5; i++){ cin>>x[i]; } 

正在访问x [5],这是不存在的。