8

たとえば、SIGABRTをキャッチして、ロングジャンプでプログラムを続行することができます。

常にabort()を呼び出す関数を呼び出すと、これがスタックオーバーフローにつながる可能性があるのではないかと思います。

ユニットテストでassertマクロ(taht呼び出しabort)を使用したいので、それを知る必要があります。アサーションが失敗した場合は、次の単体テストを続行します。

4

3 に答える 3

2

abortスタックをクリアする必要はありません。longjmpスタックポインタをの位置に巻き戻すという点で「クリア」しますsetjmp。他のすべてが正しければ、繰り返し呼び出しlongjmpて、setjmpスタックオーバーフローを引き起こしません。

ただし、longjmp通常の実行パスはスキップされます。通常の実行パスは、それ自体でリソースリークを呼び出す可能性があります。このコードを考えてみましょう:

char *s = malloc(...);
... use s ...
free(s);

「...uses ...」の部分がlongjmpコード外の関数を呼び出すfreeと、呼び出される機会がなく、リークが発生します。同じことが、開いているファイル、ソケットを閉じる、共有メモリセグメントを解放する、分岐した子を刈り取るなどにも当てはまります。

このためlongjmp、Cプログラミングではめったに使用されません。私のアドバイスはassert、プログラムを終了するつもりがない場合は避けることです。単体テストで別のマクロを使用するか、マクロを提供するテストフレームワークに切り替えてください。

于 2013-01-23T13:29:28.387 に答える
1

longjmpはスタックを巻き戻しませんが、スタックポインタを変更します。

setjmpが呼び出された関数が戻った場合、対応するjmp_bufオブジェクトでlongjmpを安全に使用することはできなくなります。これは、関数が戻るときにスタックフレームが無効になるためです。longjmpを呼び出すと、スタックポインターが復元されます。これは、関数が返されるため、存在せず、上書き/破損した可能性のあるスタックフレームを指します。

于 2013-01-23T13:28:07.480 に答える
1

POSIXを想定すると、は非同期シグナルセーフであると指定されているため(また、このシグナルは非同期ではないため) 、 raisedbylongjmpから抜け出すための呼び出しは有効です。(プレーンCでは、シグナルハンドラーからほとんどすべてを実行することはUBであるため、通常、話をするのは興味深いケースではありません。)ただし、結果として、自分のプログラムの状態に一貫性がないことを確認するのはユーザーの責任です。プログラムがプログラムフローの直後またはかなり後に他の方法でUBを呼び出すようにする方法。SIGABRTabortabort

そうは言っても、あなたの提案は非常に悪い形式のエラー処理であるというuser4815162342に同意します。中止したくない場合は、を呼び出さずabortに、代わりに独自のエラー処理関数を作成してください。

于 2013-01-23T13:41:56.647 に答える