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

C++ 如何在未初始化的内存传递给函数时断言/测试,c++,c,visual-studio-2008,memory-management,C++,C,Visual Studio 2008,Memory Management,我有一种情况,我的代码的一部分有时会被传递到未初始化的内存中。我正在寻找一种方法,在使用调试堆运行时,当出现这种情况时,我可以断言这种情况。这是一个可以在某些地方使用的函数,用于跟踪bug: void foo( char* data, int dataBytes ) { assert( !hasUninitialisedData(data,dataBytes) ); //, This is what we would like ... } 我已经看到有像valgrind这样的工

我有一种情况,我的代码的一部分有时会被传递到未初始化的内存中。我正在寻找一种方法,在使用调试堆运行时,当出现这种情况时,我可以断言这种情况。这是一个可以在某些地方使用的函数,用于跟踪bug:

void foo( char* data, int dataBytes )
{
    assert( !hasUninitialisedData(data,dataBytes) ); //, This is what we would like
    ...
}
我已经看到有像valgrind这样的工具,当我在windows上运行时,有DrMemory。但是,它们在应用程序外部运行,因此在开发人员遇到问题时不会发现问题。更重要的是,这些函数为Qt和其他不相关的函数提供了数千份报告,使事情变得不可能

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

我主要感兴趣的是可能有一个CRT函数、库、VisualStudio断点或其他帮助函数来执行这种检查。“感觉”好像已经有一个地方了,我还没找到,所以如果有人能为这种情况提供一些好的解决方案,我将不胜感激


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

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

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

我现在已经实现了一个函数,它基本上完成了在wiki上找到魔法数字列表后的预期功能:

/**对可能未初始化的数据执行检查
\备注可能会错误地报告未初始化的数据,因为在极少数情况下,所包含的数据始终可能与幻数匹配,因此此功能应仅用于初始识别未初始化的数据
*/
bool hasUninitialisedData(常量字符*数据,大小\u t lenData)
{
常量unsigned int kUninitialisedMagic[]=
{
0xABABABAB,//由Microsoft的HeapAlloc()用于在分配的堆内存后标记“无人地带”保护字节
0xABADCAFE,//启动此值以初始化所有可用内存以捕获错误指针
0xBAADF00D,//由Microsoft的LocalAlloc(LMEM_FIXED)用于标记未初始化的已分配堆内存
0xBADCAB1E,//断开与调试程序的连接时,返回给Microsoft eVC调试程序的错误代码
0xBeefCache,//由Microsoft.NET用作资源文件中的幻数
0xccccccCC,//微软的C++调试运行时库用来标记未初始化堆栈存储器
0xCDCDCDCD,/ /微软的C++调试运行时库使用的标记未初始化堆内存
0xDEADDEAD,//用户手动启动崩溃时使用的Microsoft Windows停止错误代码。
0xFDFDFDD,/ /微软的C++调试堆使用,在分配堆内存之前和之后标记“无人地带”保护字节
0xFEEEFEEE,//由Microsoft的HeapFree()用于标记已释放的堆内存
};
常量unsigned int kunitialisedmagiccount=sizeof(kunitialisedmagic)/sizeof(kunitialisedmagic[0]);
如果(lenData<4)返回assert(false==“没有足够的数据进行检查!”),则返回false;
对于(unsigned int i=0;i
这是一种“第二十二条军规”:如果不触发未定义的行为,就无法检查未初始化内存的内容;如果不检查内存的内容,就无法确定内存是否已初始化。解决这一问题的一种方法是要求向API传递一个
struct
/
类而不是缓冲区,并在
struct
中保留一个“is initialized”标记。不幸的是,这也不是防弹的。其目的是能够检测导致未定义行为的未初始化内存。不过,有关读取已初始化为0xCD的分配内存的问题绝不是未定义的行为。我已经更新了详细信息,因为这个内存是为第三方库提供的,并且它部分是未初始化的缓冲区,因为可能没有设置每四个整数。我仍然希望有一个Microsoft或CRT函数来执行类似的操作或执行幻数检查,除非这是唯一/最好的方法?
/** 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;
}