5

私は自分のコード (setjmp を使用) で断続的にクラッシュするバグを追跡しようとしており、次のように絞り込みました: /O2 でコンパイルすると表示され、/O2 /Oy- で表示されなくなります。フレームポインタ。

http://msdn.microsoft.com/en-us/library/2kxx5t2c(v=vs.80).aspxは、setjmp にはフレーム ポインターが必要であることを示唆しています。したがって:

  1. setjmp を使用するプログラムが /O2 でコンパイルされると、Visual C++ は、断続的なスタック破損を引き起こすコードをサイレント モードで生成するようです。これは本当ですか、それとも何か不足していますか?

  2. setjmp を呼び出す関数のみをフレーム ポインターでコンパイルする必要があるように思われます。プログラムの残りの部分 (longjmp を呼び出す関数であっても) は、フレーム ポインターを省略してもかまいません。これは本当ですか?

編集:もう少し絞り込みました。

setjmp を呼び出していた関数でフレーム ポインターを有効にしても違いはありませんでしたが、これは、コンパイラーが既にそれを実行していたためであり、実行する必要があることに明らかに気づき、自動的に実行していました。

違いがあったのは、メインでフレーム ポインターを有効にしたことです。クラッシュはメインから返ってきたので、それは思ったほど奇妙ではありません。考えてみると、setjmp の使用法を Google で簡単に検索すると、すべての例が main で実行されます。おそらく、マイクロソフトのコンパイラ チームがその方法でしかテストしなかったのでしょう。

これは慣用的な使用方法ですが、おそらく最善の回避策は、setjmp を使用する関数を main にインライン化することです。

4

3 に答える 3

3

さて、私は自己完結型のテストケースを含むバグレポートを投稿したので、うまくいけば、修正がパイプラインにあります:http: //connect.microsoft.com/VisualStudio/feedback/details/666704/visual-c-generates-不正なコード-with-omit-frame-pointer-and-setjmp

当面の間、回避策は、省略フレームポインターを使用しないか、setjmpを呼び出すコードをmainに配置するか、longjmpを呼び出す関数をsetjmpの呼び出しと同じソースファイルに配置することです。

于 2011-05-12T16:59:10.310 に答える
0

クラッシュ自体に関する詳細情報を教えてください。つまり、コンパイラが に対して生成したコードはどれですか?longjmpクラッシュは の直後に発生しlongjmpますか? 自動変数にアクセスしようとしたとき、または関数を終了しようとしたときに発生しますか?

ターゲット関数は標準のスタック フレームでコンパイルする必要があると思いますが、使用する関数に合理的な制限はないようlongjmpです。

于 2011-05-12T17:37:09.420 に答える
0

setjmp はさまざまな方法で実装されていますが、これはおそらく、特定の OS のアセンブリ実装と関係があります。

関数が __stdcall を使用してコンパイルされると、引数はフレーム ポインターを基準にして格納されます。あなたの実装は、上記のポインターに関連する setjmp への引数にアクセスしている可能性があるため、コンテキストをそれらに保存する複数のレジスターを破棄する必要はありません (これにより、setjmp のポイントの多くが台無しになるため)。Linuxカーネルではsetjmpがこのように実装されていることを覚えているようです。

もちろん、msvc が ebp を設定する命令を生成しない場合、これは機能せず、確実にクラッシュが発生します。

于 2011-11-05T17:26:28.633 に答える