249

プロセスがC++でSIGABRTを取得するシナリオは何ですか?この信号は常にプロセス内から送信されますか、それともこの信号を1つのプロセスから別のプロセスに送信できますか?

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

4

12 に答える 12

240

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

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

于 2010-08-05T09:06:28.273 に答える
60

SIGABRT重大なエラーが発生した場合にプログラムを中止するために、libcやその他のライブラリで一般的に使用されます。たとえば、glibcSIGABRTは、ダブルフリーまたはその他のヒープ破損が検出された場合にを送信します。

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

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

于 2010-08-05T09:08:45.357 に答える
53

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

kill -SIGABRT 30823

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

$ /bin/dash
$ Aborted

Aborted出力は明らかにdashSIGABRTを報告する方法です。

を使用して任意のプロセスに直接送信できます。または、プロセスは、、、またはkill(2)を介してシグナルを自身に送信できます。assert(3)abort(3)raise(3)

于 2010-08-05T09:06:24.683 に答える
19

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

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

于 2011-10-07T16:57:33.783 に答える
17

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

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

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

thread::join();

また

thread::detach();
于 2016-03-10T08:17:20.130 に答える
9

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

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

libcエラーメッセージをキャッチし、/ dev/ttyからリダイレクトします

于 2015-08-17T18:31:15.653 に答える
5

プロセスがそれ自体から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無制限

実行:./ aa

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

ここで、コアファイルをすばやく確認し、SIGABRTが実際に呼び出されたことを検証します。

gdb aa core

regsを参照してください:

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

:)

于 2017-03-29T08:20:11.270 に答える
2

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

string x[5];

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

    cin>>x[i];

}

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

于 2016-11-03T17:53:40.297 に答える
1

競技プログラミング(cp)の観点から答えますが、他のドメインにも当てはまります。

cpを実行している間、制約は非常に大きくなります。

N, M, Q:。などの変数について質問がありました1 ≤ N, M, Q < 10^5

私が犯した間違いは、サイズの2D整数配列を宣言し、10000 x 10000Codechefでのエラーにほぼ2日間C++苦労したことでした。SIGABRT

さて、計算すると:

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

配列内のセルの数:10000 x 10000

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

このような質問に対するあなたの解決策は、このサイズを許容できるので、あなたのPC(常にではない)で機能します。

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

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

結論:

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

PS:このエラーには他の理由があるかもしれません。上記はそのうちの1つでした。

于 2019-10-08T18:44:01.420 に答える
1

「@sarnold」が適切に指摘しているように、どのプロセスも他のプロセスにシグナルを送信できるため、1つのプロセスが他のプロセスにSIGABORTを送信できます。その場合、受信プロセスは、メモリなど、または他の誰かが「一律に」持っている場合は、それに送信します。

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

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

于 2019-10-30T12:32:06.277 に答える
1

最初の質問について:What are the scenarios where a process gets a SIGABRT in C++?

C ++プログラムが自動的に中止される2つの特殊なケースを考えることができます-直接呼び出すstd::abort()std::terminate()

1つ:例外の処理中に例外をスローします。

try {
    throw "abc";
}
catch (...) {
    throw "def";  // abort here
}

2:外部に伝播しようとするキャッチされない例外main()

int main(int argc, char** argv)
{
    throw "abc";  // abort here
}

C ++の専門家は、おそらくもっと特殊なケースに名前を付けることができます。

これらのリファレンスページにも多くの良い情報があります:

于 2020-12-21T19:23:05.820 に答える
0

Androidネイティブコードの場合、 https: //source.android.com/devices/tech/debug/native-crashに従ってabortが呼び出される理由は次のとおりです。

中止は意図的なものであるため興味深いものです。中止する方法はたくさんありますが(abort(3)の呼び出し、 assert(3)の失敗、Android固有の致命的なログタイプの1つを使用するなど)、すべて中止の呼び出しが含まれます。

于 2021-08-31T20:49:13.250 に答える