如何在未初始化的内存传递给函数时断言/测试

时间:2013-07-31 16:54:41

标签: c++ c visual-studio-2008 memory-management

我遇到的情况是我的代码中的一部分有时会被发送到未初始化的内存中。我正在寻找一种方法,当我使用调试堆运行时,我可以断言这种情况。这是一个可以在某些地方抛出的功能,以便在跟踪错误方面提供额外的帮助:

void foo( char* data, int dataBytes )
{
    assert( !hasUninitialisedData(data,dataBytes) ); //, This is what we would like
    ...
}

我已经看到有像valgrind这样的工具,而且我在Windows上运行的是DrMemory。然而,这些在应用程序外部运行,因此在开发人员发生时不会发现问题。更重要的是,这些为Qt和其他无关功能提供了数千份报告,使事情变得不可能。

我认为这个想法是有一个函数来搜索数组中的0xBAADFOOD,但是有一系列潜在的十六进制值,每个平台都有这些变化。存储整数时,这些十六进制值有时也可能有效,因此不确定是否有更多信息可以从调试堆中获得。

我主要感兴趣的是可能有CRT函数,库,visual-studio断点或其他辅助函数来进行这种检查。感觉就像已经存在某个地方一样,我找不到它,所以如果有人对这种情况有一些很好的解决方案,我们将不胜感激。

编辑:我应该更好地解释一下,我知道调试堆将使用一个值初始化所有分配,以尝试检测未初始化的数据。如上所述,接收的数据包含一些0xBAADFOOD值,通常内存使用0xCDCDCDCD初始化,但这是第三方库分配数据,显然有多个幻数,因此我感兴趣的是隐藏某处的广义检查。

3 个答案:

答案 0 :(得分:0)

VC ++运行时(至少在调试版本中)初始化具有特定值的所有堆分配。只要我记得,它就是同样的价值。但是,我不能记住实际价值。您可以进行快速分配测试并进行检查。

答案 1 :(得分:0)

VC ++程序的调试版本通常在启动时将未初始化的内存设置为0xCD。这在会话的生命周期内是不可靠的(一旦内存被分配/使用/解除分配,值将会改变),但它是一个可以开始的地方。

答案 2 :(得分:0)

我已经实现了一个函数,它基本上在wiki (Magic numbers)上找到魔术数列表后完成了预期的操作:

/** Performs a check for potentially unintiialised data
    \remarks May incorrectly report uninitialised data as it is always possible the contained data may match the magic numbers in rare circumstances so this function should be used for initial identification of uninitialised data only
*/
bool hasUninitialisedData( const char* data, size_t lenData )
{
    const unsigned int kUninitialisedMagic[] = 
    {
        0xABABABAB, // Used by Microsoft's HeapAlloc() to mark "no man's land" guard bytes after allocated heap memory
        0xABADCAFE, // A startup to this value to initialize all free memory to catch errant pointers
        0xBAADF00D, // Used by Microsoft's LocalAlloc(LMEM_FIXED) to mark uninitialised allocated heap memory
        0xBADCAB1E, // Error Code returned to the Microsoft eVC debugger when connection is severed to the debugger
        0xBEEFCACE, // Used by Microsoft .NET as a magic number in resource files
        0xCCCCCCCC, // Used by Microsoft's C++ debugging runtime library to mark uninitialised stack memory
        0xCDCDCDCD, // Used by Microsoft's C++ debugging runtime library to mark uninitialised heap memory
        0xDEADDEAD, // A Microsoft Windows STOP Error code used when the user manually initiates the crash.
        0xFDFDFDFD, // Used by Microsoft's C++ debugging heap to mark "no man's land" guard bytes before and after allocated heap memory
        0xFEEEFEEE, // Used by Microsoft's HeapFree() to mark freed heap memory
    };
    const unsigned int kUninitialisedMagicCount = sizeof(kUninitialisedMagic)/sizeof(kUninitialisedMagic[0]);

    if ( lenData < 4 ) return assert(false=="not enough data for checks!"), false;

    for ( unsigned int i =0; i < lenData - 4; ++i ) //< we don't check the last few bytes as keep to full 4-byte/int checks for now,  this is where the -4 comes in
    {
        for ( unsigned int iMagic = 0; iMagic < kUninitialisedMagicCount; ++iMagic )
        {
            const unsigned int* ival = reinterpret_cast<const unsigned int*>(data + i);
            if ( *ival == kUninitialisedMagic[iMagic] )
                return true;
        }
    }
    return false;
}