5

私は、セグメンテーション違反と浮動小数点エラーを適切な例外にラップすることを約束するsegvcatchライブラリに出くわしました。

キャッチされたすべての segfaults がヌル ポインター アクセスのみであるという前提条件を追加した場合 (つまり、segfaulting の前にメモリを完全に台無しにして未定義の動作を引き起こす可能性のある配列オーバーフローや無効なポインターがないこと)、このライブラリを使用しても安全ですか? nullptr segfault をキャッチした後も、プログラムはまだセマンティクスを定義していますか? 浮動小数点エラーはどうですか?彼らはより良い/異なる動作をしますか?

補足: segfault を生成するプログラムは形式が正しくなく、デバッグ/修正する必要があるというコメントはしないでください。私はそれを知っており、同意します。それでも、私はこの質問に興味があります。

4

1 に答える 1

5

安全ではありません。

シグナル ハンドラは非常に単純で、単純に間違っています。SEGV ハンドラは次のとおりです。

void default_segv()
{
    throw std::runtime_error("Segmentation fault");
}

少なくとも POSIX では、これはかなり違法です。シグナルハンドラー内から例外をスローすることは、非常に悪い考えです。

補遺
では、なぜこれが悪い考えなのでしょうか?

SIGALRM を使用すると、悪い考えよりも悪いことになります。アラームは非同期であるため、未定義の動作です。SIGSEGV と SIGBUS を使用するのは非常に悪い考えです。他の信号では、それは単に悪い考えです。うまくいくかもしれません。また、そうでない場合もあります。魔法が効かないと、結果は非常に悲惨なものになる可能性があります。

最初に SEGV を見ていきます。セグメンテーション違反とバス エラーの一般的な原因の 1 つは、スタックの破壊です。これがシグナルの原因である場合、アンワインドするスタックはありません。はthrow、別の SEGV を発生させるスタックを巻き戻そうとします。それで?私のコンピューターでは、それは惨事です。

シグナルに関係なく、シグナル ハンドラー内でのスローは RAII に関して安全ではありません。これはfree()(したがってdelete) ハンドラーのコンテキスト内での呼び出しが安全ではないためです。シグナル ハンドラーのコンテキスト内から安全に呼び出せない関数が多数あります。はハンドラーから返されないため、ハンドラー内の の後に発生するすべてのことthrowは、シグナル ハンドラーのコンテキスト内から行われます。throwthrowリターンをバイパスします。

これらの安全でない呼び出しと安全でない巻き戻しは、古いシグナルを処理しながら新しいシグナルを発生できることを意味します。この再帰シグナルは非常に問題があります。たとえば、私のコンピューターでは、シグナルが SIGSTOP に変更されます。プログラムは終了せず、コアもドロップしません。それはそこにハングアップし、-9 で強制終了するか、マシンを再起動するまで永久にフリーズします。

于 2012-09-13T17:11:21.983 に答える