C++シグナル処理をマスター:安全な割り込み管理とクリーンなプログラム終了
シグナルとは、オペレーティングシステムによってプロセスに送られる割り込みであり、プログラムを予期せず終了させる可能性があります。UNIX、Linux、macOS、WindowsシステムでCtrl+Cを押すことで割り込みを生成できます。
プログラムで捕捉できないシグナルもありますが、<csignal>ヘッダーファイルで定義されている以下のシグナルはプログラムで捕捉し、適切なアクションを取ることができます。
| 番号 | シグナルと説明 |
|---|---|
| 1 | SIGABRTabort呼び出しなどによるプログラムの異常終了 |
| 2 | SIGFPE ゼロ除算やオーバーフローなどの不正な算術演算 |
| 3 | SIGILL 不正な命令の検出 |
| 4 | SIGINT インタラクティブなアテンションシグナルの受信(Ctrl+C) |
| 5 | SIGSEGV ストレージへの無効なアクセス(セグメンテーション違反) |
| 6 | SIGTERM プログラムへの終了要求 |
signal()関数
C++のシグナル処理ライブラリは、予期せぬイベントを捕捉するためのsignal関数を提供します。構文は以下の通りです。
void (*signal (int sig, void (*func)(int)))(int);
簡単に言うと、この関数は2つの引数を取ります:シグナル番号を表す整数と、シグナルハンドラ関数へのポインタです。
以下はsignal()関数を使ってSIGINTシグナルを捕捉する簡単なC++プログラムです。プログラムで捕捉したいシグナルがあれば、signal関数でそのシグナルを登録し、シグナルハンドラと関連付ける必要があります。
#include <iostream>
#include <csignal>
using namespace std;
void signalHandler(int signum) {
cout << "Interrupt signal (" << signum << ") received.\n";
// クリーンアップ処理をここに記述
// プログラム終了
exit(signum);
}
int main() {
// SIGINTシグナルとハンドラを登録
signal(SIGINT, signalHandler);
while(1) {
cout << "Going to sleep...." << endl;
sleep(1);
}
return 0;
}
上記コードをコンパイルして実行すると、以下のような結果になります。
Going to sleep.... Going to sleep.... Going to sleep....
ここでCtrl+Cを押してプログラムを中断すると、シグナルを捕捉して以下のように出力して終了します。
Going to sleep.... Going to sleep.... Going to sleep.... Interrupt signal (2) received.
raise()関数
raise()関数を使ってシグナルを生成することもできます。この関数は整数のシグナル番号を引数に取り、以下の構文を持ちます。
int raise (signal sig);
ここでsigは送信するシグナル番号です:SIGINT、SIGABRT、SIGFPE、SIGILL、SIGSEGV、SIGTERM、SIGHUPなど。以下はraise()関数を使って内部的にシグナルを発生させる例です。
#include <iostream>
#include <csignal>
using namespace std;
void signalHandler(int signum) {
cout << "Interrupt signal (" << signum << ") received.\n";
// クリーンアップ処理をここに記述
// プログラム終了
exit(signum);
}
int main() {
int i = 0;
// SIGINTシグナルとハンドラを登録
signal(SIGINT, signalHandler);
while(++i) {
cout << "Going to sleep...." << endl;
if(i == 3) {
raise(SIGINT);
}
sleep(1);
}
return 0;
}
上記コードをコンパイルして実行すると、以下の結果が出力され自動的に終了します。
Going to sleep.... Going to sleep.... Going to sleep.... Interrupt signal (2) received.
C言語
- C++データ型完全ガイド:基本型、修飾子、ベストプラクティス
- C++演算子完全ガイド:算術・代入・関係・論理・ビット演算子と実例
- C++コメント完全ガイド:読みやすく保守しやすいコードのためのベストプラクティス
- C++クラステンプレート完全ガイド:実践的なジェネリックプログラミング
- C言語 ファイル入出力: fopen, fprintf, fread, fseek をマスターする
- C++例外処理をマスター:try、catch、throwの実践例
- C言語エラーハンドリングのマスター:ベストプラクティスとテクニック
- C++プログラミング言語:概要と主要機能
- C++定数とリテラル完全解説:型、構文、ベストプラクティス
- C++演算子完全ガイド:種類、使い方、ベストプラクティス
- C++数値型完全ガイド:実践的な使い方と数学関数