我們有一個用Visual Basic 6.0編寫的前端,它調用混合C/C++編寫的幾個後端DLL。問題是每個DLL似乎都有自己的堆,其中一個不夠大。當我們分配了足夠的內存時,堆會與程序堆棧發生衝突。 除了用C++編寫的基本DLL封裝外,每個DLL都完全用C語言編寫。每個DLL都有一些入口點。每個入口點立即調用一個C例程。我們希望增加DLL中堆的大小,但一直未能弄清楚如何做到這一點。我搜索了指導,並發現這些MSDN文章:如何在混合語言應用程序中創建堆?
http://msdn.microsoft.com/en-us/library/hh405351(v=VS.85).aspx
這些文章很有意思,但提供了矛盾的信息。在我們的問題中,似乎每個DLL都有自己的堆。這與「堆:樂趣和痛苦」文章相匹配,文章說C啓動時(C RT)庫在啓動時創建了自己的堆。 「管理堆內存」文章指出,C RT庫分配在默認進程堆外。 「Win32中的內存管理選項」文章說這種行爲取決於正在使用的C RT庫的版本。
我們通過從私有堆中分配內存來暫時解決了這個問題。但是,爲了改進這個非常大型的複雜程序的結構,我們希望從一個C++包裝器切換到真正的具有類的C++。我們非常肯定,新的自由操作符不會從我們的私有堆中分配內存,我們想知道如何控制C++在每個DLL中分配對象時使用的堆的大小。該應用程序需要從2000年到7
問題在桌面Windows-NT的所有版本中運行,
任何人都可以帶我們去明確和正確的文件是 講解了如何控制規模堆C++用來分配 對象?
有幾個人聲稱由堆分配覆蓋堆棧造成的堆棧損壞是不可能的。這是我們觀察到的。 VB前端使用它動態加載的四個DLL。每個DLL獨立於其他DLL並提供前端調用的一些方法。所有的DLL通過寫入磁盤文件的數據結構進行交流。這些數據結構都是靜態構造的。它們不包含指針,只是值類型和固定大小的值類型數組。問題DLL由文件名傳遞的單個調用調用。它旨在分配完成處理所需的大約20MB數據結構。它做了很多計算,將結果寫入磁盤,釋放20MB的數據結構,並返回和錯誤代碼。然後前端卸載DLL。在調試討論中的問題時,我們在數據結構分配代碼的開頭設置了一個斷點,並觀察calloc調用返回的內存值,並將它們與當前的堆棧指針進行比較。我們看着分配的塊接近堆棧。分配完成後,堆棧開始增長,直到堆棧重疊。最終計算結果寫入了堆並損壞了堆棧。隨着堆棧解開,它試圖返回到一個無效地址並且因分段錯誤而崩潰。
我們的每個DLL都靜態鏈接到CRT,這樣每個DLL都有自己的CRT堆和堆管理器。微軟在http://msdn.microsoft.com/en-us/library/ms235460(v=vs.80).aspx中說:
CRT庫的每個副本都有一個單獨的不同的狀態。 因此,諸如文件句柄,環境變量和 語言環境的CRT對象僅對分配或設置了這些對象的CRT副本有效。當DLL及其用戶使用CRT庫的不同副本時,無法將這些CRT對象跨越DLL邊界 傳遞,並期望它們在另一端正確拾取。
另外,因爲CRT庫的每個副本都有自己的堆管理器,所以在一個CRT庫中分配內存並將指針穿過 DLL邊界,並由另一個CRT庫的副本釋放,這是 的潛在原因堆腐敗。
我們不通過DLL之間的指針。我們沒有遇到堆腐敗,我們遇到堆棧損壞。
希望你得到一個正確的答案,但如果你不這樣做,你總是可以覆蓋'new'和'delete'運算符來處理一個私有堆。 –
謝謝。我知道我們可以做到這一點,但這是一個相當複雜的解決方案。如果我們能夠計算出如何去做,那麼增加運行時提供的堆的大小就簡單多了。我們只使用私人堆,因爲我們還沒有弄清楚這一點。 –
碰撞是不可能的。請澄清。 –