堆步行在发布模式下无法按预期工作
HeapWalk not working as expected in Release mode
所以我使用这个 HeapWalk 函数的例子来实现它到我的应用程序中。我玩了一下,当我添加时看到
HANDLE d = HeapAlloc(hHeap, 0, sizeof(int));
int* f = new(d) int;
创建堆后,将记录一些新的输出:
Allocated block Data portion begins at: 0X037307E0
Size: 4 bytes
Overhead: 28 bytes
Region index: 0
所以看到这个,我想我可以检查Entry.wFlags
,看看它是否设置为PROCESS_HEAP_ENTRY_BUSY
,以跟踪我在堆上使用的分配内存量。所以我有:
HeapLock(heap);
int totalUsedSpace = 0, totalSize = 0, largestFreeSpace = 0, largestCounter = 0;
PROCESS_HEAP_ENTRY entry;
entry.lpData = NULL;
while (HeapWalk(heap, &entry) != FALSE)
{
int entrySize = entry.cbData + entry.cbOverhead;
if ((entry.wFlags & PROCESS_HEAP_ENTRY_BUSY) != 0)
{
// We have allocated memory in this block
totalUsedSpace += entrySize;
largestCounter = 0;
}
else
{
// We do not have allocated memory in this block
largestCounter += entrySize;
if (largestCounter > largestFreeSpace)
{
// Save this value as we've found a bigger space
largestFreeSpace = largestCounter;
}
}
// Keep a track of the total size of this heap
totalSize += entrySize;
}
HeapUnlock(heap);
当内置在调试模式下时,这似乎有效(totalSize
和totalUsedSpace
是不同的值(。但是,当我在发布模式下运行时,totalUsedSpace
始终为 0。
我在发布模式下使用调试器逐步完成它,对于每个堆,它循环三次,entry.wFlags
调用HeapWalk
时,我得到了以下标志:
1 (PROCESS_HEAP_REGION)
0
2 (PROCESS_HEAP_UNCOMMITTED_RANGE)
然后它退出while
循环,GetLastError(( 按预期返回ERROR_NO_MORE_ITEMS
。
从这里我发现 0
的标志值是"免费的已提交块,即未分配或未用作控制结构"。
有谁知道为什么它在发布模式下构建时无法按预期工作?我对计算机如何处理内存没有太多经验,所以我不确定错误可能来自哪里。在谷歌上搜索没有想出任何东西,所以希望这里有人知道。
更新:我自己仍在研究这个问题,如果我使用 vmmap 监控应用程序,我可以看到该进程有 9 个堆,但是当调用GetProcessHeaps
时,它会返回有 22 个堆。此外,没有一个堆处理它返回与返回值 GetProcessHeap()
或 _get_heap_handle()
匹配项。似乎GetProcessHeaps
的行为不符合预期。以下是获取堆列表的代码:
// Count how many heaps there are and allocate enough space for them
DWORD numHeaps = GetProcessHeaps(0, NULL);
HANDLE* handles = new HANDLE[numHeaps];
// Get a handle to known heaps for us to compare against
HANDLE defaultHeap = GetProcessHeap();
HANDLE crtHeap = (HANDLE)_get_heap_handle();
// Get a list of handles to all the heaps
DWORD retVal = GetProcessHeaps(numHeaps, handles);
retVal
的值与 numHeaps
相同,表示没有错误。
应用程序验证程序之前已设置为对我的可执行文件进行整页堆验证,并且干扰了GetProcessHeaps
返回的堆。我忘记了它是几天前针对不同问题进行的设置,然后在没有清除测试的情况下关闭。调试版本中没有发生这种情况,因为应用程序生成到调试版本的不同文件名。
我们通过添加断点并查看线程的调用堆栈来设法检测到这一点。我们可以看到AV DLL已被注入,这让我们知道在哪里查找。
- 自定义内存管理器在发布模式下工作正常,但在调试模式下则不然
- 装饰器模式在 c++ 中的工作原理
- 我的代码在发布模式下不起作用,而在Qt的调试模式下工作
- 模式匹配函数的时间测量无法正常工作
- ifstream读取二进制文件在发行模式下工作,但在调试模式下不使用
- 打开文件的正确模式是什么,以便 seekp() 的工作方式与在默认模式下打开的文件相同
- 为什么在发布模式下无法访问 for 循环,但在调试中它工作正常
- Python在调试模式下以C 工作,但在EXE文件中不工作
- 该代码在调试模式下工作,但在发布模式C 中不起作用
- 当主GUI线程被阻塞时,如何从工作线程创建无模式对话框
- 如何在 QT 框架工作C++中使用变量作为正则表达式模式
- 在发行模式下开放的软崩溃(调试工作正常)
- 在 C++11 中,lambda 队列是否是工作队列的良好设计模式
- 工作线程队列的这种变体是某种模式或通用结构吗?
- 混合模式程序集(C++/CLI项目)在.NET Core上工作吗
- 在QIODevice::Append模式下打开的QFile意外工作.这是一个Qt错误吗
- 模式功能:它是如何工作的
- zmq呼吸机/工作人员/水槽模式与子流程一起不工作
- 在调试器模式下工作,但在最终版本中不起作用.为什么
- ZeroMq PUB/SUB 模式无法正常工作