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

How to assert/test when uninitialised memory is passed to function

本文关键字:何断言 断言 测试 初始化 内存 函数      更新时间:2023-10-16

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

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

我看到有像valgrind这样的工具,当我在窗口上运行时,有DrMemory。然而,这些程序在应用程序外部运行,因此当开发人员遇到问题时,不会发现问题。更重要的是,这些函数为Qt和其他不相关的函数抛出了数千个报告,使事情变得不可能。

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

我主要感兴趣的是,可能有一个CRT函数、库、visual studio断点或其他辅助函数来进行这种检查。"感觉"某个地方应该已经有了,我还找不到,所以如果有人能为这种情况找到一些好的解决方案,我将不胜感激。

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

VC++运行时,至少在调试构建中,使用特定值初始化所有堆分配。从我记事起,它就一直是一样的价值观。然而,我记不起实际价值了。你可以做一个快速的分配测试和检查。

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

我现在已经实现了一个函数,它基本上是在维基上找到幻数列表后完成的:

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