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

我找到了上述问题的解决方案,用初始化/未初始化的指针和不同的长度类型对其进行了测试。

在测试标题中,我添加了#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

而不是逐字节比较,您可能应该使用正确的填充或字长,并测试每个字的任何字节是否被初始化。这样,您可能会使用填充和构造函数绕过编译器,在填充的短于单词的字段之间留下未初始化的字节。

为了测试真正的填充大小,从臀部拍摄,下面的代码应该非常可靠:

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;
  }
}

编辑:您仍然需要这两个对象,但您不再将它们相互比较,您只需将每个初始化数据与 memset 值进行比较,如果其中一个对象有任何变化,则意味着这个词被触及(也在另一个,它只是有可能被初始化为与你 memset 相同的值)。

于 2012-10-25T08:23:39.147 回答
0

您的测试检查对象的每个字节是否已被构造函数覆盖。作为一个直接的内存检查,它看起来不错,尽管如果该类包含其他不一定完全初始化自己的对象,您可能会遇到麻烦。

也就是说,我的主要问题是:这真的是一个有效的测试吗?例如,CSplitVector类中的每个属性都由初始化列表初始化是否至关重要?您是否有一些此时可能不需要初始化?另外,如何检查属性是否设置为您期望的值?

于 2012-10-25T08:07:06.910 回答