vector<string>
私のプログラムは、 のシグナル ハンドラ内のの内容への読み取り専用アクセスを実行する必要がありますSIGINT
。(代わりに、固定長の C 文字列の固定サイズの配列を使用することもできます。) プログラムは、POSIX 環境で実行するように設計されています。
vector::operator[]
とはvector::size()
非同期セーフ (またはシグナル セーフ) ですか?
vector<string>
私のプログラムは、 のシグナル ハンドラ内のの内容への読み取り専用アクセスを実行する必要がありますSIGINT
。(代わりに、固定長の C 文字列の固定サイズの配列を使用することもできます。) プログラムは、POSIX 環境で実行するように設計されています。
vector::operator[]
とはvector::size()
非同期セーフ (またはシグナル セーフ) ですか?
いいえ、安全ではありません。C++11 1.9/6:
抽象マシンの処理がシグナルの受信によって中断されると、どちらでもないオブジェクトの値
- タイプ
volatile std::sig_atomic_t
も- ロックフリーのアトミック オブジェクト (29.4)
これら 2 つのカテゴリのいずれにも属さず、ハンドラーによって変更されたオブジェクトの値は未定義になります。
C++を考えると、Angewの答えは正しいです。質問で、より強力な保証を提供できる POSIX 環境に言及しているため、別の回答が必要です。
プロセスがマルチスレッドである場合、またはプロセスがシングルスレッドであり、次の結果以外でシグナル ハンドラーが実行される場合:
abort()
、raise()
、kill()
、pthread_kill()
、またはを呼び出して、sigqueue()
ブロックされていないシグナルを生成するプロセス保留中のシグナルがブロック解除され、ブロック解除した呼び出しが返される前に配信される
errno
として宣言されたオブジェクトに値を代入する以外に、シグナルハンドラが静的記憶域期間以外のオブジェクトを参照するvolatile sig_atomic_t
場合、またはシグナルハンドラが、この標準で定義されている関数のうちの 1 つ以外の関数を呼び出す場合、動作は未定義です。次の表。
出典: The Open Group Base Specifications Issue 7 IEEE Std 1003.1、2013 年版、2.4.3
これは... まだ非常に弱い保証です。私がこれを理解できる限り:
vector::operator[]
安全ではありません。固定配列は安全ではありません。配列が静的でない場合、固定配列へのアクセスは安全です。
なんで?vector::operator[]
実装方法を正確に指定するのではなく、前提条件と事後条件のみを指定します。配列の要素へのアクセスは可能です (配列が静的でない場合)。これは、シグナリングの前に (vec.data()
またはを使用して&vec[0]
) ポインターを作成し、ポインターを介して要素にアクセスする場合、ベクトル要素へのアクセスも安全であることを意味します。 .
編集:もともと私はsigaction
関数を認識していなかったので、それを見逃していました-signal
シグナルハンドラーでローカル配列にしかアクセスできませんでしたが、sigaction
自動および動的配列へのポインターを提供できます。ただし、シグナル ハンドラーでできるだけ少ないことを行うというアドバイスは、ここでも適用されます。
結論: シグナル ハンドラーでやりすぎです。できるだけ少なくしてみてください。1 つのアプローチは、(タイプの) フラグに代入してvolatile sig_atomic_t
返すことです。コードは後でフラグがトリガーされたかどうかを確認できます (たとえば、イベント ループで)。