2

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

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 初始化的,但这是分配数据的第三方库,显然有多个幻数,因此我很感兴趣是否隐藏在某处的通用检查。

4

3 回答 3

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;
}
于 2013-08-01T08:52:17.607 回答
0

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

于 2013-07-31T16:59:27.410 回答
0

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

于 2013-07-31T16:59:37.597 回答