什么时候进程得到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],这是不存在的。