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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3413166/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 12:47:12  来源:igfitidea点击:

When does a process get SIGABRT (signal 6)?

c++sigabrt

提问by Shree

What are the scenarios where a process gets a SIGABRT in C++? Does this signal always come from within the process or can this signal be sent from one process to another?

进程在 C++ 中获得 SIGABRT 的场景是什么?这个信号总是来自进程内部还是可以从一个进程发送到另一个进程?

Is there a way to identify which process is sending this signal?

有没有办法识别哪个进程正在发送这个信号?

采纳答案by Nordic Mainframe

abort()sends the calling process the SIGABRTsignal, this is how abort()basically works.

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

abort()is usually called by library functions which detect an internal error or some seriously broken constraint. For example malloc()will call abort()if its internal structures are damaged by a heap overflow.

abort()通常由检测内部错误或某些严重破坏的约束的库函数调用。例如,如果其内部结构因堆溢出而损坏,malloc()则调用abort()

回答by IanH

SIGABRTis commonly used by libc and other libraries to abort the program in case of critical errors. For example, glibc sends an SIGABRTin case of a detected double-free or other heap corruptions.

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

Also, most assertimplementations make use of SIGABRTin case of a failed assert.

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

Furthermore, SIGABRTcan be sent from any other process like any other signal. Of course, the sending process needs to run as same user or root.

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

回答by sarnold

You can send any signal to any process using the kill(2)interface:

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

kill -SIGABRT 30823

kill -SIGABRT 30823

30823 was a dashprocess I started, so I could easily find the process I wanted to kill.

30823 是dash我启动的一个进程,所以我可以很容易地找到我想杀死的进程。

$ /bin/dash
$ Aborted

The Abortedoutput is apparently how dashreports a SIGABRT.

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

It can be sent directly to any process using kill(2), or a process can send the signal to itself via assert(3), abort(3), or raise(3).

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

回答by Mig

It usually happens when there is a problem with memory allocation.

它通常发生在内存分配出现问题时。

It happened to me when my program was trying to allocate an array with negative size.

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

回答by Sudip Bhattarai

There's another simple cause in case of c++.

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

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

i.e. scope of thread ended but you forgot to call either

即线程范围结束,但你忘了调用

thread::join();

or

或者

thread::detach();

回答by Mark Lakata

The GNU libc will print out information to /dev/ttyregarding some fatal conditions before it calls abort()(which then triggers SIGABRT), but if you are running your program as a service or otherwise not in a real terminal window, these message can get lost, because there is no tty to display the messages.

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

See my post on redirecting libc to write to stderr instead of /dev/tty:

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

Catching libc error messages, redirecting from /dev/tty

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

回答by Alexander Kruman

A case when process get SIGABRT from itself: Hrvoje mentioned about a buried pure virtual being called from ctor generating an abort, i recreated an example for this. Here when d is to be constructed, it first calls its base class A ctor, and passes inside pointer to itself. the A ctor calls pure virtual method before table was filled with valid pointer, because d is not constructed yet.

进程从自身获取 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;
}

compile: g++ -o aa aa.cpp

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

ulimit -c unlimited

ulimit -c 无限制

run: ./aa

运行:./aa

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

now lets quickly see the core file, and validate that SIGABRT was indeed called:

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

gdb aa core

see regs:

见规则:

i r
rdx            0x6      6
rsi            0x69a    1690
rdi            0x69a    1690
rip            0x7feae3170c37

check code:

检查代码:

disas 0x7feae3170c37

禁用 0x7feae3170c37

mov    
string x[5];

for(int i=1; i<=5; i++){

    cin>>x[i];

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

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

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

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

:)

:)

回答by anonymous

In my case, it was due to an input in an array at an index equal to the length of the array.

就我而言,这是由于数组中索引等于数组长度的输入所致。

##代码##

x[5] is being accessed which is not present.

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

回答by Fooo

As "@sarnold", aptly pointed out, any process can send signal to any other process, hence, one process can send SIGABORT to other process & in that case the receiving process is unable to distinguish whether its coming because of its own tweaking of memory etc, or someone else has "unicastly", send to it.

正如“@sarnold”恰当地指出的那样,任何进程都可以向任何其他进程发送信号,因此,一个进程可以将 SIGABORT 发送到另一个进程,在这种情况下,接收进程无法区分它是否由于自己的调整而到来内存等,或者其他人“单播”发送给它。

In one of the systems I worked there is one deadlock detector which actually detects if process is coming out of some task by giving heart beat or not. If not, then it declares the process is in deadlock state and sends SIGABORT to it.

在我工作的其中一个系统中,有一个死锁检测器,它实际上通过提供心跳来检测进程是否从某个任务中出来。如果不是,则声明进程处于死锁状态并向其发送 SIGABORT。

I just wanted to share this prospective with reference to question asked.

我只是想参考提出的问题来分享这个前景。

回答by Genius

I will give my answer from a competitive programming(cp)perspective, but it applies to other domains as well.

我将从竞争性编程(cp)的角度给出我的答案,但它也适用于其他领域。

Many a times while doing cp, constraints are quite large.

很多时候在做cp时,约束是相当大的。

For example: I had a question with a variables N, M, Qsuch that 1 ≤ N, M, Q < 10^5.

例如:我有一个关于变量的问题,N, M, Q例如1 ≤ N, M, Q < 10^5.

The mistake I was making was I declared a 2D integer array of size 10000 x 10000in C++and struggled with the SIGABRTerror at Codechef for almost 2 days.

我犯的错误是我声明了一个大小为10000 x 10000in的二维整数数组,C++SIGABRT在 Codechef 上与错误斗争了将近 2 天。

Now, if we calculate :

现在,如果我们计算:

Typical size of an integer : 4 bytes

No. of cells in our array : 10000 x 10000

Total size (in bytes) : 400000000 bytes = 4*10^8 ≈ 400 MB

整数的典型大小:4 字节

我们阵列中的单元格数量:10000 x 10000

总大小(以字节为单位):400000000 字节 = 4*10^8 ≈ 400 MB

Your solutions to such questions will work on your PC(not always) as it can afford this size.

您对此类问题的解决方案将适用于您的 PC(并非总是如此),因为它可以负担得起这个尺寸。

But the resources at coding sites(online judges) is limited to few KBs.

但是编码站点(在线评委)的资源仅限于几个 KB。

Hence, the SIGABRTerror and other such errors.

因此,SIGABRT错误和其他此类错误。

Conclusion:

结论:

In such questions, we ought not to declare an array or vector or any other DS of this size, but our task is to make our algorithm such efficient that it works without them(DS) or with less memory.

在这些问题中,我们不应该声明一个数组或向量或任何其他这种大小的 DS,但我们的任务是使我们的算法如此高效,以使其在没有它们 (DS) 或内存更少的情况下也能工作。

PS: There might be other reasons for this error; above was one of them.

PS:这个错误可能还有其他原因;以上就是其中之一。