2

奇妙な動作をするプログラムがあり、おそらく動作が未定義です。関数の戻りアドレスが変更されているように見えることがありますが、何が原因なのかわかりません。

戻りアドレスは常に同じアドレスに変更されます。これは、コントロールが到達できない関数内のアサーションです。returnステートメントを実行するはずのときに、代わりにアサーションのある行に直接ジャンプすることを確認するために、デバッガーでプログラムを停止することができました。

このコードは、関数がどのように機能するかを近似しています。

int foo(Vector t)
   double sum = 0;
   for(unsgined int i=0; i<t.size();++i){
        sum += t[i]; 
   }
   double limit = bar(); // bar returns a value between 0 and 1
   double a=0;
   for(double i=0; i<10; i++){
       a += f(i)/sum; // f(1)/sum + ... + f(10)/sum = 1.0f
       if(a>3)return a;
   }
   //shoudn'get here
   assert(false); // ... then this line is executed
}

これは私がこれまでに試したことです:

  • すべての std::vector[]演算子を切り替え.atて、誤ってメモリに書き込むのを防ぎます
  • すべての値渡しの値が const であることを確認しました。
  • スイッチをオン-Wallにし-Werror-pedantic-errors、gcc で
  • valgrind でプログラムを実行しました

私はいくつかの を取得しますinvalid read of size 8が、それらは qt に由来するように見えるので、どうすればよいかわかりません。これが問題でしょうか?

このエラーは、プログラムをしばらく実行して特定の入力値を与えた場合にのみ発生し、デバッグ ビルドよりもリリース ビルドで頻繁に発生します。

EDIT: コンソールアプリケーション(qtがロードされていない)で問題を再現することができたので、問題の原因となったイベントをシミュレートしました。

何人かが示唆したように、おそらくqtのデバッガーの経験が不足しているため、実際にアサーションに到達する原因を誤って判断したことがわかりました。実際の問題は、ループ条件として使用される double i の浮動小数点エラーでした。

ソフトマックスを実装していましたが、特定の入力で exp(x) がゼロに丸められました。

今、私は問題を解決したので、私はそれを言い換えるかもしれません. 丸め誤差などの問題を自動的にチェックする方法はありますか。つまり、たとえば 0/0 でブレークしますか?

4

1 に答える 1

1

簡単な答えは次のとおりです。

浮動小数点例外条件が発生したかどうかを判断する最も移植性の高い方法は、fenv.h で C によって提供される浮動小数点例外機能を使用することです。

残念ながら、これは完璧とは言えません。

https://www.securecoding.cert.org/confluence/display/seccode/FLP04-C.+Check+floating-point+inputs+for+exceptional+valueshttps://www.securecodingの両方を読むことをお勧めします 。 .cert.org/confluence/display/seccode/FLP03-C.+Detect+and+handle+floating-point+errors は、あなたが提起している正確な質問に簡潔に対処します:

丸め誤差などの問題を自動的にチェックする方法はありますか。

于 2013-06-27T13:43:23.037 に答える