-1

IIR フィルターとヒストグラムを使用して数学的計算を実行するコードを作成しました。コードは 100% 移植可能で、再入可能で、システム コールを行わず (memset を除く)、倍精度の const と初期化された変数を持ち、math.h、string.h、stdint.h、および stddef.h のみを含みます。組み込みプロセッサで実行するように作られています。

Windows MinGW GCC または Borland C++ を使用してコードをコンパイルおよび実行すると、すべての単体テストに合格します。これは、Linux64 GCC プラットフォームでは発生しません。さらに調査したところ、アルゴリズムが少し不安定になり、出力値が安定した結果に収束せず、代わりに結果がゆっくりと無限大になるため、テストの 1 つが失敗することが示されました。

ほとんどのコードは浮動小数点の倍精度を使用していますが、一部の変数では単精度も使用しています。

この問題に対処する方法について助けが必要です。コードの完全な移植性を保証する必要がありますが、どこを見ればよいかわかりません。また、コードはここに投稿するのに十分な大きさなので、指示があればフォローします。

これは、Linux でのモジュールのコンパイル行です。

gcc -O3 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/flickerModule.d" -MT"src/flickerModule.d" -o "src/flickerModule.o" "../src/flickerModule.c"

これは、Windows でのモジュールのコンパイル行です。

gcc -O0 -g3 -Wall -c -fmessage-length=0 -o src\flickerModule.o ..\src\flickerModule.c

ここに、コードのすべての依存関係を示します。

fanl@fanl-STI:~/WorkFelipe/Codigos/re7k_eclipsewkspace/flicker_unittest/src$ grep -H -n -E 'mem|sqrt|floor' flickerModule.c
flickerModule.c:76: memset(filt, 0x00, sizeof(struct s_filter));
flickerModule.c:81: memset(filt, 0x00, sizeof(struct s_filter));
flickerModule.c:89: memset(&histo->buf, 0x00, sizeof(uint32_t) * NUM_CLASSES);
flickerModule.c:162:    return (floorf(x + 0.5));
flickerModule.c:189:            memset(&histn, 0x00, sizeof(float) * NUM_CLASSES);
flickerModule.c:262:        hp->Urms_meio_ciclo = sqrt(hp->Acc_Urms_meio_ciclo / NUM_AMOSTRAS_MEIO_CICLO_60Hz);
flickerModule.c:370:        return (sqrtf(saida));
flickerModule.c:393:        p->GanhoNormalizaEntradaFlickerMeter = 1.0 / (p->halfPeriod.Urms_meio_ciclo * sqrt(2));
flickerModule.c:419:            dbg->Prms = sqrt(dbg->Acc_Prms / (NUM_AMOSTRAS_1MIN / FATOR_DOWN1));
4

3 に答える 3

1

LDRA/Lint などのツールを使用して、静的解析を実行してみましたか? このようなツールは、多くの場合、問題のある領域を特定することができます。また、コードは警告を出さずに最大警告をオンにしてコンパイルします。コンパイラは、多くの場合、潜在的な問題も強調します。個人的には、gcc で -Wall -Werror を使用することをお勧めします。

于 2013-07-04T19:31:29.590 に答える
0

(注:これは答えではありませんが、フォーマットが必要です)。sizeof (type)すべての行を対応するsizeof exprバージョンに置き換えてみることができます。これは万能薬ではありませんが、スタイル上のヒントであり、より堅牢なコードにつながります。まず、次のように変更できます。

memset(filt, 0x00, sizeof(struct s_filter));

memset(&histo->buf, 0x00, sizeof(uint32_t) * NUM_CLASSES);

memset(&histn, 0x00, sizeof(float) * NUM_CLASSES);

の中へ:

memset(filt,0, sizeof *filt);

memset(&histo->buf, 0, sizeof histo->buf * NUM_CLASSES);
return (floorf(x + 0.5));
memset(&histn, 0, sizeof histn * NUM_CLASSES);

構造体の定義を表示していないため、実際のサイズがわからないため、これは間違っている可能性があります。ところで:16進定数は必要ありません0x00。とにかくゼロです。

更新:物事を除外するためだけに(arrest the ususal suspects:: 鑑別診断):単一のスレッドでコードのテスト実行を試してください。スレッド化メカニズムは、プラットフォーム間で異なる場合があります。

于 2013-07-04T20:48:20.503 に答える