プロセスはいつSIGABRT(シグナル6)を取得しますか?


202

プロセスがC ++でSIGABRTを取得するシナリオは何ですか?このシグナルは常にプロセス内から発生しますか、またはこのシグナルをあるプロセスから別のプロセスに送信できますか?

このシグナルを送信しているプロセスを特定する方法はありますか?


3
いくつかの方法があります。プログラムを作成した場合、最も簡単な方法は、その情報を出力し、戻る前にそのストリームをフラッシュするSIGABRTのシグナルハンドラーを登録することです。2番目に簡単な方法は、strace内でプログラムを実行することです。3番目に簡単な方法は、プログラムがクラッシュしたときにコアファイルを生成し、コアダンプを介して確認することです。
パルティアンショット

回答:


195

abort()呼び出しプロセスにSIGABRTシグナルを送信しますabort()。これが基本的に機能する方法です。

abort()通常は、内部エラーまたは深刻に壊れた制約を検出するライブラリ関数によって呼び出されます。たとえば、内部構造がヒープオーバーフローによって破損した場合malloc()に呼び出さabort()れます。


27
私の場合、ほとんどの場合、SIGABRTは、初期化されていない/破損したポインターlibcを呼び出そうとして送信されfree()ました
Grandrew

コードのどこかに、コンストラクター内から埋め込まれた純粋な仮想関数呼び出しがある場合、それもSIGABRTシグナルになる可能性がありますか?純粋な仮想呼び出しがあることを示すエラーが表示されるので、次の行でSIGABRTメッセージが表示され、アプリケーションがクラッシュするか、オペレーティングシステムによって閉じられます。ありがとう。
Hrvoje 2017年

2
MacOSでは、約1000のファイルハンドルを閉じずに開くためのSIGABRTを取得しました。私たちのテストでは、モックする代わりに、Close()メソッドを持たないより一般的なリーダータイプでファイルを抽象化したため、忘れられました。素晴らしい報道をしました。:rolleyes:
Zyl

52

SIGABRT重大なエラーが発生した場合にプログラムを中止するために、libcおよび他のライブラリーによって一般的に使用されます。たとえば、glibc SIGABRTは、double-freeまたは他のヒープの破損が検出された場合にを送信します。

また、ほとんどのassert実装SIGABRTは、アサートが失敗した場合に利用します。

さらに、SIGABRT他のシグナルと同様に、他のプロセスから送信できます。もちろん、送信プロセスは同じユーザーまたはrootとして実行する必要があります。


49

kill(2)インターフェイスを使用して、任意のプロセスに任意のシグナルを送信できます。

kill -SIGABRT 30823

30823はdash私が始めたプロセスだったので、自分が殺したいプロセスを簡単に見つけることができました。

$ /bin/dash
$ Aborted

Aborted出力はどのように明らかにされdashSIGABRTを報告します。

これは、使用して任意のプロセスに直接送信することができkill(2)、またはプロセスは、ビア自体に信号を送ることができるassert(3)abort(3)またはraise(3)


17

通常、メモリの割り当てに問題がある場合に発生します。

これは、プログラムが負のサイズの配列を割り当てようとしたときに起こりました。


14

c ++の場合、もう1つの単純な原因があります。

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

つまり、スレッドのスコープは終了しましたが、いずれかを呼び出すのを忘れました

thread::join();

または

thread::detach();

7

GNU libcは/dev/tty、呼び出す前にいくつかの致命的な状態に関する情報を出力しますabort()(その後、トリガーしますSIGABRT)が、プログラムをサービスとして実行している場合、または実際の端末ウィンドウで実行していない場合、これらのメッセージは失われる可能性があります。メッセージを表示するtty。

/ dev / ttyの代わりにstderrに書き込むためのlibcのリダイレクトに関する私の投稿を参照してください。

/ dev / ttyからリダイレクトするlibcエラーメッセージのキャッチ


4

プロセスがそれ自体からSIGABRTを取得する場合:Hrvojeは、アボートを生成するctorから呼び出される埋め込まれた純粋な仮想について言及しましたが、この例を再作成しました。ここでdが構築されるとき、それは最初にその基本クラスAのctorを呼び出し、それ自体へのポインターの内部を渡します。dがまだ作成されていないため、テーブルが有効なポインタで満たされる前に、A ctorは純粋な仮想メソッドを呼び出します。

#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 unlimited

実行:./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

チェックコード:

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

:)


2

私の場合、それは配列の長さに等しいインデックスの配列の入力が原因でした。

string x[5];

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

    cin>>x[i];

}

存在しないx [5]にアクセスしています。


1

「@sarnold」が適切に指摘したように、任意のプロセスが他のプロセスにシグナルを送信できるため、1つのプロセスがSIGABORTを他のプロセスに送信できます。メモリなど、または他の誰かが「ユニキャスト」で送信します。

私が働いたシステムの1つには、ハートビートを与えるかどうかによってプロセスがタスクから出ているかどうかを実際に検出する1つのデッドロック検出器があります。そうでない場合は、プロセスがデッドロック状態であることを宣言し、SIGABORTを送信します。

私は尋ねられた質問を参照してこの見込みを共有したかっただけです。


0

私は競争プログラミング(cp)の観点から回答しますが、それは他のドメインにも適用されます。

多くの場合、cpの実行中、制約は非常に大きくなります。

たとえば、次のN, M, Qような変数を使用して質問をしました1 ≤ N, M, Q < 10^5

私が作っていたミス私はサイズの配列整数2Dに宣言された10000 x 10000C++とに苦しんSIGABRTほぼ2日間Codechefでエラー。

ここで、計算すると:

整数の一般的なサイズ:4バイト

アレイ内のセルの数:10000 x 10000

合計サイズ(バイト):400000000バイト= 4 * 10 ^ 8≈400 MB

このサイズの余裕があるので、そのような質問に対するソリューションはPCで機能します(常にではありません)。

ただし、コーディングサイト(オンラインジャッジ)のリソースは数KBに制限されています。

したがって、SIGABRTエラーおよび他のそのようなエラー。

結論:

そのような質問では、このサイズの配列やベクトル、またはその他のDSを宣言するべきではありませんが、私たちのタスクは、アルゴリズムなしで効率的に(DS)または少ないメモリで機能するようにすることです。

PS:このエラーには他の理由が考えられます。上記の1つでした。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.