在c++中,进程获得SIGABRT的场景是什么?这个信号总是来自进程内部还是可以从一个进程发送到另一个进程?
有没有办法确定是哪个进程在发送这个信号?
在c++中,进程获得SIGABRT的场景是什么?这个信号总是来自进程内部还是可以从一个进程发送到另一个进程?
有没有办法确定是哪个进程在发送这个信号?
当前回答
对于Android原生代码,以下是根据https://source.android.com/devices/tech/debug/native-crash调用abort的一些原因:
中止之所以有趣,是因为它们是有意为之的。中止有许多不同的方法(包括调用abort(3), assert失败(3),使用android特定的致命日志类型之一),但都涉及调用abort。
其他回答
在我的例子中,这是由于在一个数组中输入的一个索引等于数组的长度。
string x[5];
for(int i=1; i<=5; i++){
cin>>x[i];
}
X[5]正在被访问,但不存在。
进程从自身获取SIGABRT的情况: Hrvoje提到了一个从ctor调用的被掩埋的纯虚拟生成一个中止,我为此重新创建了一个例子。 这里,当要构造d时,它首先调用它的基类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
无限制
:运行。/ aa
pure virtual method called
terminate called without an active exception
Aborted (core dumped)
现在让我们快速查看核心文件,并验证SIGABRT确实被调用:
gdb aa core
见规则:
i r
rdx 0x6 6
rsi 0x69a 1690
rdi 0x69a 1690
rip 0x7feae3170c37
校验码:
灾害学0 x7feae3170c37
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
:)
关于第一个问题:在c++中进程获得SIGABRT的场景是什么?
我可以想到两种c++程序自动中止的特殊情况——不是通过直接调用std::abort()或std::terminate():
一:在处理异常时抛出异常。
try {
throw "abc";
}
catch (...) {
throw "def"; // abort here
}
二:试图在main()外部传播的未捕获异常。
int main(int argc, char** argv)
{
throw "abc"; // abort here
}
c++专家可能还能举出更多的特殊情况。
在这些参考页面上也有很多好的信息:
https://en.cppreference.com/w/cpp/utility/program/abort https://en.cppreference.com/w/cpp/error/terminate
它通常发生在内存分配有问题的时候。
当我的程序试图分配一个 大小为负的数组。
对于Android原生代码,以下是根据https://source.android.com/devices/tech/debug/native-crash调用abort的一些原因:
中止之所以有趣,是因为它们是有意为之的。中止有许多不同的方法(包括调用abort(3), assert失败(3),使用android特定的致命日志类型之一),但都涉及调用abort。