2012-12-06 51 views
2

我的問題是我有一個我無法修改的32位DLL。在正常操作下,DLL有時可能需要大約1.5G的內存。P/Invoke是否爲目標DLL提供更少的內存?

當我使用C++ /非託管代碼測試程序時,該DLL只會在大約2個演出時耗盡內存。這是預期的,因爲這是可用於32位進程的最大大小。因此,在正常操作下,DLL運行良好。

當我從一個C#應用程序調用DLL時,它本身需要大約250 MB,當整個過程達到約1.4演出時,DLL出錯。我的問題是P/Invoke爲32位進程提供更少的內存使用?有什麼辦法可以讓它更多嗎?

編輯:P /調用函數實際上是從我的主要assumbly引用的C#程序集調用的。不知道這是否以任何方式相關。

回答

3

區別可能是因爲您的託管程序比非託管程序需求更大。所以有更少的資源留給你的DLL。即使有剩餘內存,程序也可能會耗盡內存。當地址空間碎片化並且虛擬內存分配程序找不到足夠大的連續內存塊來滿足分配請求時,會發生這種情況。

對於我懷疑的事情,你可以做的事情不多。我懷疑你會試圖讓你的託管進程消耗更少的資源。如果您在64位系統上運行,並且您的進程可以識別大地址,那麼您的進程可以訪問4GB的內存。

將.net可執行文件標記爲LARGEADDRESSAWARE可能會有所幫助。有關詳細信息,請參閱另一個SO問題:How to make a .NET application "large address aware"?總之,你需要運行EDITBIN工具來標記你的可執行文件:

EDITBIN /LARGEADDRESSAWARE YourExeName.exe 

要知道,雖然在32位操作系統上你幾乎與2GB的限制卡住了。是的,您可以使用/ 3GB開關啓動您的系統,但通常不會提示。

另一個顯而易見的選擇是將DLL放入進程外的COM服務器。通過將它放在不同的進程中,您可以將.net運行時保留在進程之外,併爲飢餓的DLL留下儘可能多的空間。

+0

它被一個64位機器上運行,但DLL是32位。我可以使我的項目64位,但據我所知這意味着我無法訪問32位DLL。 此外,我提到的1.4個演出是託管應用程序+進程的總內存(它們顯示在任務管理器中組合),因此它仍未達到2個演出組合。 –

+0

@Jasmin我猜存在內存碎片,這是它在1.4GB時失敗的原因。看看您是否可以將託管應用程序標記爲'LARGEADDRESSAWARE',可能會有一些里程碑。 –

+0

非常感謝內存碎片的簡要解釋。可能就是這樣發生的事情。 LARGEADDRESSAWARE似乎沒有幫助 - 可能需要嘗試其他解決方案。你知道在這種情況下製作一個CLI/C++包裝DLL可能會有一些好處,而不是直接從C#調用P/Invokes嗎? –

1

,這可能發生,因爲你的C++ aplication有LARGEADDRESSAWARE選項設置和C#應用程序犯規

在C

+ +應用程序在本文中定義 - >連接器 - >系統 - >啓用大地址=「是/ LARGEADDRESSAWARE」

嘗試加入以下後生成事件

call "$(DevEnvDir)..\..\vc\vcvarsall.bat" x86 
"$(DevEnvDir)..\..\vc\bin\EditBin.exe" "$(TargetPath)" /LARGEADDRESSAWARE 
+0

如果C++應用程序是LARGEADDRESSAWARE,那麼您會驚訝於它在2GB時發飆。 –

+0

欣賞響應。 C++應用程序實際上並沒有設置該標誌,從我目前可以知道的情況來看,將它設置在我的C#應用​​程序中並不是很不幸。 –

+0

@JasminLaferriere你正在得到哪個錯誤? – makc

相關問題