---------- Block 195475 at 0x1875D078: 8 bytes ---------- CRT Alloc ID: 230764 Leak Hash: 0x017BFFF5, Count: 1, Total 8 bytes
有一个LeakHash
,这个会重复打印
DWORD callstackCRC = 0; if (info->callStack) callstackCRC = CalculateCRC32(info->size, info->callStack->getHashValue()); // 这里会计算这个hashValue Report(L" Leak Hash: 0x%08X, Count: %Iu, Total %Iu bytes\n", callstackCRC, blockLeaksCount, size * blockLeaksCount); // hashValue的算法,这个hash值是RtlCaptureStackBackTrace自动计算的 ULONG BackTraceHash; // maxFrames为堆栈的实际帧数 maxframes = RtlCaptureStackBackTrace(0, maxframes, reinterpret_cast<PVOID*>(myFrames), &BackTraceHash); m_hashValue = BackTraceHash;
RtlCaptureStackBackTrace
RtlCaptureStackBackTrace
是一个 Windows 内部 API,用于获取当前线程的调用堆栈信息。该函数定义在 ntdll.dll
动态链接库中,因此需要使用动态链接库函数(DLL function)的方式来调用。
RtlCaptureStackBackTrace
函数的声明如下:
USHORT RtlCaptureStackBackTrace( _In_ ULONG FramesToSkip, _In_ ULONG FramesToCapture, _Out_opt_ PVOID *BackTrace, _Out_opt_ PULONG BackTraceHash );
该函数的参数说明如下:
FramesToSkip
:指定从当前调用栈中跳过多少个帧(函数调用)。通常为 0。FramesToCapture
:指定需要捕获的调用栈帧数。如果该值为 0,则不会捕获任何帧。BackTrace
:可选参数,用于返回捕获到的调用栈信息。如果该参数为 NULL,则表示不需要获取调用栈信息。BackTraceHash
:可选参数,用于返回调用栈信息的哈希值。如果该参数为 NULL,则表示不需要计算哈希值。
CRTD
"C Run-Time Dynamic Link Library"
crtd_malloc
crtd_malloc
是 Visual C++ 运行库(CRT)中的一个用于分配内存的函数,它与标准库中的 malloc
函数类似,但 crtd_malloc
会在分配的内存块前面添加一段包含调试信息的头部,这些调试信息包括内存块大小、源代码文件名和行号等。因此,使用 crtd_malloc
分配的内存块可以被 Visual Studio 调试器识别,并在内存泄漏或越界等问题发生时提供更加详细的调试信息。
DWORD displacement = 0; DbgTrace(L"dbghelp32.dll %i: SymGetLineFromAddrW64\n", GetCurrentThreadId()); // 获取指定地址所在的代码行信息 BOOL foundline = g_DbgHelp.SymGetLineFromAddrW64(g_currentProcess, programCounter, &displacement, &sourceInfo, locker); bool isFrameInternal = false; if (foundline && !showInternalFrames) { // 判断是否为内置模块,里面是通过简单粗暴的字符串比较实现的 if (isInternalModule(sourceInfo.FileName)) { // Don't show frames in files internal to the heap. isFrameInternal = true; } }
发现一段神奇的代码,开源作者原来是在F盘进行开发的
new_array_nothrow
new_array_nothrow
是 C++ 标准库中提供的一个函数,用于在任何内存分配失败时返回 nullptr
,而不是抛出一个 bad_alloc
异常。该函数是在 <new>
头文件中声明的。
其函数原型如下:
c++Copy Code void* operator new[](std::size_t size, const std::nothrow_t& tag) noexcept;
在使用 new_array_nothrow
时,需要指定一个类型大小或字节数作为第一个参数,该参数告诉编译器需要分配多少空间来存储对象数组。由于该函数接受一个名为 const std::nothrow_t&
的标记参数,因此它可以在内存分配失败时返回一个 nullptr 指针,而不是抛出一个异常。这使得该函数更加适用于实现异常处理机制较为简单的应用程序。
想要泄露报告不重复打印,开启选项即可:
AggregateDuplicates = yes