【问题标题】:HeapAlloc fails intermittentlyHeapAlloc 间歇性失败
【发布时间】:2011-10-21 02:40:19
【问题描述】:

我们有一个 DLL(使用 VC2005 构建)代表调用应用程序进行一些处理。这种处理需要相当多的内存。 DLL 通过 heapAlloc 创建此内存,如下所示:

//Allocate space
myStruct* pStackSpace = (myStruct*)::HeapAlloc(m_hStackHeap, 0, sizeof(myStruct));

...
do some processing here
...

//Free space
::HeapFree(m_hStackHeap, 0, pStackSpace);

堆是通过以下方式分配的:

m_hStackHeap = ::HeapCreate(0, sizeof(myStruct)*10, 0);

在创建之后,我们实际上分配了 20 个 myStruct,然后释放它们以确保它能够处理这些问题。所以我们知道有足够的空间。

问题是在某些情况下 HeapAlloc 返回 NULL。如果发生这种情况,我们会执行HeapValidate(m_hStackHeap, 0, NULL),它总是返回非零(意味着一切正常)。所以我们知道堆没问题。

我们还同意我们永远不会同时有超过 10 个并发分配,因此应该有足够的空间,因为最初的 heapCreate 保留了那么多。

对 HeapAlloc 的下一次调用通常会成功。这种行为非常零星。它会正常工作,然后分配几次失败,然后再次开始正常工作。

有什么想法吗?

【问题讨论】:

  • 我的假设是跟踪并发分配肯定有问题。您如何跟踪以确保您只有 10 个?
  • 您是否通过了 HEAP_GENERATE_EXCEPTIONS 作为选项?它会告诉您它遇到了两种故障模式(内存不足与堆损坏)中的哪一种。
  • 由于您使用的是 DLL,您是否正在访问由一个进程从另一个进程创建的堆? 私有堆对象的内存只有创建它的进程才能访问。 -- 来自 MSDN
  • 如何创建堆?如果您使用的是有限大小的堆(例如,在创建时非零 dwMaximumSize),即使堆非常大,每个分配都被限制为 512K 之类的东西。 sizeof(myStruct)*10 给你多大尺寸?
  • Andre 它不受限制: ::HeapCreate(0, sizeof(myStruct)*10, 0) 我们将零作为最大值。

标签: c++ windows dll visual-studio-2005 heapalloc


【解决方案1】:

您可以使用自定义 ALLOC 和 FREE 例程来保持适当大小的池,而不是使用自定义堆。

这是通过将结构与一个包含 NEXT 指针的简单对象和一个包含指针的全局变量联合来完成的。

如果您不在,请从全局堆中分配一个新的。

你会在哪里销毁所有这些堆。

【讨论】:

    【解决方案2】:

    该行为表明这可能是由于堆碎片造成的。您可能有足够的总堆空间来满足请求,但没有足够大的空闲块。尝试使用低碎片堆。你可以通过调用 HeapSetInformation() 来启用 LFH。请注意,如果在 HeapCreate() 中指定了 HEAP_NO_SERIALIZE 标志,则不能使用 LFH。

    【讨论】:

    • 我总是分配相同的大小,所以我认为碎片不会成为问题?
    • 嗯...他在HeapCreate 中使用 dwMaximumSize==0,这意味着堆可以增长,所以即使碎片是严重的问题,堆也应该能够长时间保持“增长”时间。
    • @Sam:不清楚你总是分配相同的大小。如果这是真的,那么你是对的,碎片化不应该是一个问题。但是,我想确定一下很容易尝试。这里还有一些有用的数字。这个结构有多大?
    • @Branko:一个可增长的堆!=一个无限的堆。
    • @cary 好点尝试没有坏处。我去做。至于大小,我们分配的结构约为 2MB。在创建堆之后,我也会立即进行完整性检查,如下所示:` int size = 20; myStruct** pFullStackData= new myStruct*[size]; for (int i=0; i
    【解决方案3】:

    2mb 结构?考虑使用 VirtualAlloc 和分配/释放指针列表。

    【讨论】:

    • 除非我弄错了,否则 HeapAlloc 将映射到 VirtualAlloc,尤其是在创建堆时 dwMaximumSize 设置为零时
    • 您没有弄错,但是在这种特殊情况下,这将大大减少开销,因为分配已经是 2 > 4096 的固定幂。
    猜你喜欢
    • 2019-04-18
    • 1970-01-01
    • 1970-01-01
    • 2017-04-19
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 2019-08-22
    相关资源
    最近更新 更多