2011-08-05 161 views
1

我們有一個DLL(使用VC2005構建)代表調用應用程序進行一些處理。這個處理需要相當多的內存。該DLL創建通過heapAlloc這種記憶像這樣: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個myStructs,然後釋放他們只是爲了確保它搞定。所以我們知道有足夠的空間。

問題是在某些情況下HeapAlloc返回NULL。如果發生這種情況,我們會做一個總是返回非零的HeapValidate(m_hStackHeap, 0, NULL)(意思是說一切都很好)。所以我們知道堆是可以的。

我們還承認,我們從來沒有超過10個併發分配,所以應該有足夠的空間,因爲初始heapCreate保留了很多空間。

HeapAlloc的下一次調用通常會成功。行爲非常零星。它會正常工作,然後不分配幾次,然後再次開始正常工作。

關於正在發生的事情的任何想法?

+0

我的假設是在跟蹤併發分配時一定會有問題。你如何跟蹤以確保你只有10個? – Chad

+2

您是否已通過HEAP_GENERATE_EXCEPTIONS作爲選項?它會告訴你哪個失敗模式(內存不足或損壞的堆)被擊中。 –

+0

由於您使用DLL,您是否正在訪問堆,由另一個進程創建? *私有堆對象的內存只能由創建它的進程訪問。* - 來自MSDN –

回答

0

而不是使用自定義堆,您可以使用自定義ALLOC和FREE例程保持適當大小的池。

這是通過將結構與包含NEXT指針和一個包含指針的全局變量的簡單對象進行聯合來完成的。

如果你外出從全局堆中分配一個新的。

你會在哪裏銷燬所有這些堆。

1

該行爲表明它可能歸因於堆碎片。您可能有足夠的堆空間來滿足請求,但沒有足夠大的空閒塊。嘗試使用低碎片堆。你可以通過調用HeapSetInformation()來啓用LFH。請注意,如果您在HeapCreate()中指定了HEAP_NO_SERIALIZE標誌,則不能使用LFH。

+0

我總是分配相同的大小,所以我會碎片不會是一個問題? – Sam

+0

嗯......他在HeapCreate中使用了dwMaximumSize == 0,這意味着堆可以增長,所以即使碎片是嚴重的問題,堆應該能夠長時間「長大」它。 –

+0

@Sam:不清楚你總是分配相同的大小。如果那是真的,那麼你說對,碎片不應該成爲問題。但是,我很容易確定。這裏也有幫助的是一些數字。這個結構有多大? –

0

2mb結構?考慮使用VirtualAlloc和一個alloc/free指針列表。

+0

除非我誤會HeapAlloc將映射到VirtualAlloc,尤其是在將dwMaximumSize設置爲零的情況下創建Heap時 – Sam

+0

您沒有錯,但是這會減少在這種特殊情況下的開銷,因爲分配已經是固定功率2> 4096 。 – Joshua