2

すべてのクラス属性がコンストラクターで初期化されているかどうかを確認するテストに取り組んでいます。私の現在のソリューションは、非ポインター属性に対して機能します。

void CSplitVectorTest::TestConstructorInitialization()
{
    const size_t memorySize = sizeof(CSplitVector);
    char* pBuffer1 = (char*) malloc(memorySize);
    char* pBuffer2 = (char*) malloc(memorySize);
    memset(pBuffer1,'?',memorySize);
    memset(pBuffer2,'-',memorySize);
    new(pBuffer1) CSplitVector;
    new(pBuffer2) CSplitVector;
    const bool bObjectsAreEqual = memcmp(pBuffer1,pBuffer2,memorySize)==0;
    if (!TEST(bObjectsAreEqual))
    {
        COMMENT("Constructor initialization list not complete!");
    }
    free(pBuffer1);
    free(pBuffer2);
}

ポインタが初期化されているかどうかをテストするためにどのように改善できるか考えていますか?

4

3 に答える 3

0

バイトごとに比較する代わりに、適切なパディングまたはワード サイズを使用し、各ワードのいずれかのバイトが初期化されたかどうかをテストする必要があります。そうすれば、パディングとコンストラクターを使用してコンパイラーを回避し、パディングされた単語より短いフィールドの間に初期化されていないバイトを残すことができます。

実際のパディング サイズをテストするには、腰から撮影します。次のコードは、かなり確実に行う必要があります。

struct PaddingTest {
  volatile char c; // volatile probably not needed, but will not hurt either
  volatile int i;

  static int getCharPadding() { 
    PaddingTest *t = new PaddingTest;
    int diff = (int)(&(t->i)) - (int)&((t->c));
    delete t;
    return diff;
  }
}

編集: 2 つのオブジェクトは引き続き必要ですが、それらを互いに比較する必要はありません。初期化された各データを memset 値と比較するだけで、いずれかのオブジェクトに変更がある場合は、単語が変更されたことを意味します (もう一方のオブジェクトでも)。 、memset と同じ値に初期化された可能性があります)。

于 2012-10-25T08:23:39.147 に答える
0

上記の問題の解決策を見つけ、初期化された/初期化されていないポインターとさまざまな長さの型でテストしました。

テストヘッダーに #pragma pack(1) を追加しました (gcc で作業しています)

#pragma pack(1)
#include <CSplitVector>

テストは少し複雑になりました:

void CSplitVectorTest::TestConstructorInitialization()
{
    const size_t memorySize = sizeof(CSplitVector);
    char* pBuffer = (char*) malloc(memorySize);
    memset(pBuffer,'?',memorySize);
    CSplitVector* pSplitVector = new(pBuffer) CSplitVector;

    // find pointers for all '?'
    QList<char*> aFound;
    char* pFoundChar = (char*) memchr(pBuffer,'?',memorySize);
    while (pFoundChar)
    {
        aFound.append(pFoundChar);
        char* pStartFrom = pFoundChar+1;
        pFoundChar = (char*) memchr(pStartFrom,'?',memorySize-(int)(pStartFrom-pBuffer));
    }
    // if there are any '?'....
    if (aFound.count())
    {
        // allocate the same area with '-'...
        pSplitVector->~CSplitVector();
        memset(pBuffer,'-',memorySize);
        pSplitVector = new(pBuffer) CSplitVector;
        // and check if places found before contain '-'
        while (aFound.count())
        {
            pFoundChar = aFound.takeFirst();
            if (*pFoundChar=='-')
            {
                // if yes then class has uninitialized attribute
                TEST_FAILED("Constructor initialization list not complete!");
                pSplitVector->~CSplitVector();
                free(pBuffer);
                return;
            }
        }
    }
    // if no then all attributes are initialized
    pSplitVector->~CSplitVector();
    free(pBuffer);
    TEST(true);
}

このソリューションの欠陥を指摘してください。

于 2012-10-25T11:45:39.293 に答える
0

テストは、オブジェクトのすべてのバイトがコンストラクターによって上書きされたかどうかを確認します。単純なメモリ チェックとしては問題ないように見えますが、クラスに他のオブジェクトが含まれており、それらのオブジェクトが必ずしも完全に初期化されていない場合は、問題が発生する可能性があります。

そうは言っても、私の主な質問は次のとおりです。それは本当に効果的なテストですか? たとえば、CSplitVectorクラスのすべての属性が初期化リストによって初期化されることは重要ですか? この時点で初期化する必要のないものはありますか? また、属性が期待どおりの値に設定されているかどうかを確認してみてはどうでしょうか。

于 2012-10-25T08:07:06.910 に答える