ユーザー定義のデストラクタを持つクラスがあります。クラスが最初にインスタンス化され、プログラムの実行中にSIGINTが発行された場合(UNIXでCTRL + Cを使用)、デストラクタが呼び出されますか?SIGSTP(UNIXではCTRL + Z)の動作は何ですか?
3 に答える
いいえ、デフォルトでは、ほとんどのシグナルにより、プログラムが即座に異常終了します。
ただし、ほとんどの信号の既定の動作は簡単に変更できます。
このコードは、通常のすべてのデストラクタの呼び出しを含め、シグナルでプログラムを正常に終了させる方法を示しています。
#include <iostream>
#include <signal.h>
#include <unistd.h>
#include <cstring>
#include <atomic>
std::atomic<bool> quit(false); // signal flag
void got_signal(int)
{
quit.store(true);
}
class Foo
{
public:
~Foo() { std::cout << "destructor\n"; }
};
int main(void)
{
struct sigaction sa;
memset( &sa, 0, sizeof(sa) );
sa.sa_handler = got_signal;
sigfillset(&sa.sa_mask);
sigaction(SIGINT,&sa,NULL);
Foo foo; // needs destruction before exit
while (true)
{
// do real work here...
sleep(1);
if( quit.load() ) break; // exit normally after SIGINT
}
return 0;
}
このプログラムを実行して Control-C を押すと、「destructor」という単語が表示されるはずです。シグナル ハンドラー関数 (got_signal) は、自分が何をしているのかを本当に理解していない限り、フラグを設定して静かに戻る以外はほとんど何もしないことに注意してください。
上記のように、ほとんどのシグナルはキャッチ可能ですが、SIGKILL は制御できません。SIGKILL は暴走したプロセスを強制終了するための最後の方法であり、ユーザーがプロセスをコールドでフリーズできる SIGSTOP ではないためです。必要に応じて SIGTSTP (control-Z) をキャッチできることに注意してください。ただし、シグナルに関心があるのがデストラクタの動作だけである場合は、その必要はありません。すべてのデストラクタが有効な状態で正常に終了します。
これらのシグナルを自分で処理しない場合、いいえ、デストラクタは呼び出されません。ただし、オペレーティングシステムは、プログラムの終了時にプログラムが使用したすべてのリソースを再利用します。
シグナルを自分で処理したい場合は、sigaction
標準ライブラリ関数をチェックすることを検討してください。
試してみよう:
#include <stdio.h>
#include <unistd.h>
class Foo {
public:
Foo() {};
~Foo() { printf("Yay!\n"); }
} bar;
int main(int argc, char **argv) {
sleep(5);
}
その後:
$ g++ -o test ./test.cc
$ ./test
^C
$ ./test
Yay!
だから私は恐れていません、あなたはそれを捕まえる必要があります。
についてSIGSTOP
は、キャッチできず、aSIGCONT
が送信されるまで処理を一時停止します。