1

開いているファイルのフラッシュやスタックトレースの印刷など、ingassertだけでなくもっと便利なことをしたいと思っています。abort

アサーションの実装方法について説明しているAndreiAlexandrescuによるアサーションなどのアサーションに関する記事をいくつか読みました。ただし、プログラムで使用されているサードパーティのライブラリでも、アサートハンドラを自分のものに置き換えたいと思います。私が使用するほとんどの(すべてではない)コンパイラー(gcc、MSVC、clang)とライブラリー(Qt、boost)には、ユーザー定義のアサートハンドラーを設定するオプションがあることを理解しています。ただし、現時点では、アサーションの機能を使用することに興味がないAbort,Retry,Ignoreため、コンパイラー/ライブラリ固有のアサーションハンドラーのコードを調べていません。

私が理解しているように、信号を送信するassert呼び出しは、この信号をトラップして有用なタスクを実行できますか?abortSIGABRT

4

1 に答える 1

2

assert()独自の実装でハイジャックするのはどうですか?Unixシステムでは、LD_PRELOADトリックを使用してハイジャックできます__assert_failassert()それ自体は、後者を呼び出すマクロにすぎません)。

別の可能性は、あなたが提案するようにSIGABRTをキャプチャすることです。ただし、いくつかの要件があります。

  1. への呼び出しをassert()、SIGABRTが受信される他の考えられる原因と区別する方法。これはkill()、別のスレッドまたはプロセスからの呼び出し、あるいはabort()ヒープ管理機能の健全性チェックからの呼び出しである可能性があります(free()malloc()...)。これは、プロセスの実行スタックまたは一部のシステムで渡されたコンテキストをチェックすることにより、ABRTシグナルハンドラーによって実行できsigaction()ます(そのvoid *パラメーターは誰も使用方法を知りません)。

  2. SIGABRTをキャプチャする場合は、シグナルハンドラーが「合法的に」多くのことを実行することを許可されていないことを覚えておく必要があります(printfの呼び出しでさえも)。

    sigwait()したがって、 (実装方法に基づいて、これはオプションではない可能性があります)シグナルを永続的に停止する専用スレッドを用意するかabort()、シグナルを受信するたびにシグナルハンドラーから通知を受けて、作業の大部分を実行できるようにすることをお勧めします。シグナルハンドラコンテキストから。

    また、その実装でSIGABRTがabort()特に呼び出し元のスレッドに送信される場合、その受信は同期され、非同期の安全でない関数を自由に呼び出すことができることに注意することが重要です。

  3. シグナルを自分でキャプチャし、スレッドのシグナルマスクを変更することで、言及したサードパーティライブラリのシグナル動作に影響を与える可能性があります(SIGABRT自体をキャプチャしている可能性があります)。

  4. 独自のシグナルハンドラーを使用してSIGABRTをキャプチャした場合でも、シグナルは呼び出しから送信されたabort()ため、通常の実行に戻ることはできません(alarm(8)からの引用)。

SIGABRTシグナルが無視された場合、または戻るハンドラーによってキャッチされた場合でも、abort ()関数はプロセスを終了します。これは、SIGABRTのデフォルトの処理を復元してから、信号をもう一度上げることによって行われます。

于 2013-02-14T07:41:45.197 に答える