进程何时获得SIGABRT(信号6)?

Shr*_*ree 188 c++ sigabrt

进程在C++中获取SIGABRT的场景是什么?此信号是否始终来自过程中,或者此信号是否可以从一个过程发送到另一个过程?

有没有办法确定哪个进程正在发送此信号?

Nor*_*ame 179

abort()发送调用进程SIGABRT信号,这abort()基本上是如何工作的.

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

  • 在大多数情况下,SIGABRT由`libc`发送,试图在非初始化/损坏的指针上调用`free()` (25认同)
  • 在 MacOS 上,我们使用 SIGABRT 来打开大约 1000 个文件句柄而不关闭它们。我们的测试没有模拟,而是使用更通用的读取器类型抽象文件,该类型没有 `Close()` 方法,所以它被遗忘了。虽然有很大的覆盖面。:翻白眼: (2认同)

sar*_*old 49

您可以使用该kill(2)界面向任何进程发送任何信号:

kill -SIGABRT 30823

30823是dash我开始的一个过程,所以我很容易找到我想要杀死的过程.

$ /bin/dash
$ Aborted
Run Code Online (Sandbox Code Playgroud)

Aborted输出显然是如何dash报道一个SIGABRT.

它可以直接使用被发送到任何过程kill(2)或方法可以通过将信号发送到本身assert(3),abort(3)raise(3).


Ian*_*anH 48

SIGABRTlibc和其他库通常使用它来在出现严重错误时中止程序.例如,glibc SIGABRT在检测到双重释放或其他堆损坏的情况下发送.

此外,大多数assert实现都SIGABRT在断言失败的情况下使用.

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


Mig*_*Mig 16

它通常发生在内存分配问题时.

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


Sud*_*rai 12

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

std::thread::~thread{
    if((joinable ())
        std::terminate ();
}
Run Code Online (Sandbox Code Playgroud)

即线程范围已结束但您忘记调用

thread::join();
Run Code Online (Sandbox Code Playgroud)

要么

thread::detach();
Run Code Online (Sandbox Code Playgroud)


Mar*_*ata 7

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

请参阅我关于重定向libc以写入stderr而不是/ dev/tty的帖子:

捕获libc错误消息,从/ dev/tty重定向


小智 5

进程从自身获取 SIGABRT 的情况:Hrvoje 提到了从生成中止的 ctor 调用的掩埋纯虚拟,我为此重新创建了一个示例。这里当要构造 d 时,它首先调用其基类 A ctor,并将内部指针传递给自身。A ctor 在 table 填充有效指针之前调用纯虚拟方法,因为 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;
}
Run Code Online (Sandbox Code Playgroud)

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

ulimit -c 无限制

运行:./aa

pure virtual method called
terminate called without an active exception
Aborted (core dumped)
Run Code Online (Sandbox Code Playgroud)

现在让我们快速查看核心文件,并验证确实调用了 SIGABRT:

gdb aa core
Run Code Online (Sandbox Code Playgroud)

见规则:

i r
rdx            0x6      6
rsi            0x69a    1690
rdi            0x69a    1690
rip            0x7feae3170c37
Run Code Online (Sandbox Code Playgroud)

检查代码:

disas 0x7feae3170c37

mov    $0xea,%eax  = 234  <- this is the kill syscall, sends signal to process
syscall   <-----
Run Code Online (Sandbox Code Playgroud)

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

:)