1

この質問を書いているときに、組み込みアプリケーション ビルドと非組み込みアプリケーション ビルドのために 2 つのバージョンの Qt を使用している可能性があることに気付きました。私たちは皆、を使用してgcc version 4.5.2 (Ubuntu/Linaro 4.5.2-8ubuntu4)います。私のビルド環境は次のとおりです。

QMake version 2.01a
Using Qt version 4.7.3 in /usr/local/Trolltech/QtEmbedded-4.7.3/lib

私の同僚の少なくとも 1 人が以下を使用しています。

QMake version 2.01a
Using Qt version 4.7.2 in /usr/lib

2 人の同僚が、私の計算ライブラリを使用するスタンドアロン アプリケーションを作成したときに問題に遭遇しました。私たちの主要なアプリケーションとスタンドアロンの単体テスト アプリケーションは正常に動作し、調査の結果、コードに問題は見つかりませんでした。私は、ビルド環境またはコンパイラに何らかの根本的な問題があるに違いないと結論付けました。どちらの場合も、異常/非標準の動作を分離したからです。私が分離したケースは次のとおりです。

void className::functionName(float newDeltaTime)
{
    float zero_ = 0;
    std::cout << "newDeltaTime: " << newDeltaTime << std::endl;
    std::cout << "zero_: " << zero_ << std::endl;
    std::cout << "newDeltaTime > zero_: " << (newDeltaTime > zero_) << std::endl;
    std::cout << "newDeltaTime > zero_: " << (newDeltaTime > zero_) << std::endl;
    std::cout << "newDeltaTime > zero_: " << (newDeltaTime > zero_) << std::endl;
...

これは以下を出力します:

newDeltaTime: 0.2
zero_: 0
newDeltaTime > zero_: 0
newDeltaTime > zero_: 1
newDeltaTime > zero_: 1

gdb (QtCreator によって実行される) を使用すると、各行で正しい (破損していない) 変数の値が表示されます。それが私にとって本当に奇妙なことでした。デバッガーに表示されるように変数に変更はありませんが、まったく同じ式が 2 回目に異なる値を生成します。

もともと、私はいくつかのエラーチェックを行っていましたがif(newDeltaTime > 0) { //do something } else { //log and throw }、上司は、値 0.2 で例外をスローしているコードを示しました (上記を参照)。私は問題を理解できませんでした。ロギングを追加すると、コードが機能し始めましたが、ロギングのブール式の値が正しくないことに気付きました。最後に、式を複数回ログに記録することを考えた結果、上記の出力が得られました。

地面がぐらぐらしているような気がします - これが起こる原因は何ですか? すべてがエラーなしでコンパイルされ、式を 2 回評価して結果を 2 回目に使用すると、問題なく動作するように見えます。私は、単一のイベントの混乱が発生する可能性がある場合の投票ロジック (宇宙放射線が回路に衝突し、ロジックを妥協する) に精通していますが、ここでそれが必要だと考えるとぞっとします...

4

1 に答える 1

2

これが起こる原因は何ですか?

私が考えることができる唯一のものは

  • コンパイラ (ヘッダー) と使用しているコンパイラの不一致libstdc++
  • スタックを破壊する信号処理コード

リストした出力が常に再現可能である場合、2 番目の理由はそれではなく、1 番目の理由だけが残ります。

最適化されていないコードでこの動作を観察した場合、私がこれにアプローチする方法: GDB の最初のstd::cout << "newDeltaTime > zero_: " <<...行にブレークポイントを設定し、その行の実行後に. 再度実行し、今度は で GDB ウォッチポイントを設定し、値が破損している場所を正確に確認します (おそらく libstdc++ 内のどこか)。newDeltaTime0.2watch *(float*)&newDeltaTime

ABI最適化されたコードでのみこれを観察すると、事態はより複雑になり、これを効果的にデバッグする前に s と呼び出し規約について知る必要があります。

于 2013-03-25T04:02:51.160 に答える