2

私はUnitTest++フレームワークを使用して、担当するCコードに単体テストを実装しています。最終製品は埋め込まれ、const構造を使用して構成情報を保持します。ターゲットホストは非同期で構成を変更できるため、構造体のメンバーはすべて揮発性です。一部の構造も揮発性として宣言されています。

const_castを使用して、UnitTest Windows 7ホストでvolatileキーワードがない構造インスタンスを変更しようとすると、セグメンテーション違反が発生します。これは私には理にかなっています。ただし、構造体インスタンスがvolatileキーワードで宣言されている場合、テストは合格です。これは私には意味がありません。

これは、Win7でのgccの問題を示す簡単なコード例です。定義値を切り替えると、構造体の揮発性インスタンスが使用されているかどうかに応じて、segfaultが表示されるかどうかが決まります。

typedef struct
{
    volatile int foo;
    volatile int bar;
} TestStruct;

const TestStruct constStruct = { 1, 2};
volatile const TestStruct volatileConstStruct = { 3, 4};

#define SEG_FAULT 0

int main(void)
{
    TestStruct * constPtr = const_cast<TestStruct*>(&constStruct);
    TestStruct * constVolPtr = const_cast<TestStruct*>(&volatileConstStruct);

    #if(SEG_FAULT == 0)
        constVolPtr->foo = 10;
    #else
        constPtr->foo = 20;
    #endif
}

volatileキーワードがセグメンテーション違反の回避策を提示する理由を誰かが理解するのを手伝ってもらえますか?また、すべての構造インスタンスにvolatileキーワードを追加せずに、単体テスト用に構造内の値を変更できるようにする方法を誰かが提案できますか?

編集:

私はあなたがCでこれを行うことができることをちょうど発見しました:

#define const

上記の効果的な「constundefine」をテストフィクスチャに含めると、ターゲットコンパイラがconstキーワードを認識し、構造をフラッシュメモリに正しく配置できるようになります。ただし、UnitTest ++コンパイラのプリプロセッサはconstキーワードを削除するため、テストフィクスチャは構造体を変更できます。

このソリューションの欠点は、関数呼び出しの正しいconst操作を検証する単体テストを追加できないことです。ただし、構造体インスタンスからconstを削除することはできません(データをフラッシュに配置する必要があります)ので、これは私が耐えなければならない欠点のようです。

4

2 に答える 2

4

なぜこの奇妙な行動?を使用したオブジェクト
の変更は未定義動作です。非constオブジェクトへのポインタがあり、そのオブジェクトへのポインタをポイントしたい場合に 使用されます。constconst_cast
const_castconst

なぜそれが動作するのvolatileですか?
わからない。ただし、それはまだ未定義の動作であり、それが機能することは幸運です。

Undefined Behaviorの問題は、すべての安全な賭けがオフになっていて、プログラムが何らかの動作を示す可能性があることです。動作しているように見える場合と動作しない場合があります。クラッシュしたり、奇妙な動作を示したりする可能性があります。
未定義動作を示すコードを記述しないことをお勧めします。これにより、そのような状況に対する正当な説明を節約できます。

これを解決する方法は?
変更するオブジェクトをとして宣言しないconstでください。プログラム/テストの過程でオブジェクトを変更する予定なので、オブジェクトを変更しないでくださいconst。現在、構造体オブジェクトは不変(const)であるとコンパイラーに約束していますが、後で変更することでそのコントラクトを破ります。あなたがそれを守ることができる場合にのみ、この約束をしてください。

于 2012-01-31T19:28:19.423 に答える
0

標準の脚注が答えを与えると思います。(脚注は規範的ではないことに注意してください。)

標準ドラフトN1570の§6.7.3:

132)実装は、揮発性ではないconstオブジェクトをストレージの読み取り専用領域に配置する場合があります。

これは、volatileキーワードで定義された構造が、定義されているにもかかわらず、読み取り/書き込みメモリに配置されることを意味しconstます。

どちらも揮発性のメンバーが含まれているため、コンパイラは構造体を読み取り専用メモリに配置することは許可されていないと主張する人もいるかもしれません。もし私があなたなら、コンパイラのバグレポートを送ります。

volatileキーワードがセグメンテーション違反の回避策を提示する理由を誰かが理解するのを手伝ってもらえますか?また、すべての構造インスタンスにvolatileキーワードを追加せずに、単体テスト用に構造内の値を変更できるようにする方法を誰かが提案できますか?

できません。constオブジェクトは読み取り専用メモリに配置され、書き込みを行うとセグメンテーション違反が発生します。ドロップするconstか追加しますvolatile-ドロップすることを強くお勧めしconstます。

于 2012-01-31T20:15:02.793 に答える