2009-04-28 194 views
9

在我的C++ DLL函數中,我將std :: string返回給我的c#應用程序。它幾乎是這樣的:將std :: string從C++ DLL返回到c#程序 - >指定給RtlFreeHeap的無效地址

std::string g_DllName = "MyDLL"; 

extern "C" THUNDER_API const char* __stdcall GetDLLName() 
{ 
    return g_DllName.c_str(); 
} 

但是,當我的C#代碼調用這個函數,我在輸出窗口得到這個消息:

Invalid Address specified to RtlFreeHeap(00150000, 0012D8D8) 

C#中的函數聲明如下:

[DllImport("MyDll", EntryPoint = "GetDLLName")] 
    [return: MarshalAs(UnmanagedType.LPStr)] 
    public static extern string GetDLLName(); 

從我在網上可以找到的信息可以看出,當新版本(調試版本或發行版本等)與刪除版本之間存在不一致時,會顯示此消息。但我不確定這是否是我的情況。所以我不確定究竟是什麼原因造成的。也許馬歇爾可能與它有關係?

任何想法?

謝謝!

+0

你可以查閱一下你發現即a)如果您使用的是正確的(調試)庫建立調試等和b)在這兩個調試出現此問題,發佈版本和C)嘗試使用/ clr:pure而不是/ clr作爲您的C++ dll。 – dirkgently 2009-04-28 17:50:20

回答

12

我設法找到問題。這就是C#定義完成的方式。根據我的理解,將MarshallAs(UnmanagedType.LPStr)與字符串返回類型組合使用,可以在字符串完成時嘗試釋放字符串。但是因爲字符串來自C++ DLL,並且很可能是完全不同的內存管理器,所以它失敗了。即使它沒有失敗,我也不希望它被釋放。

我找到了解決辦法是改變C#聲明本(C++代碼不變):

[DllImport("MyDll", EntryPoint = "GetDLLName")] 
public static extern IntPtr GetDLLName(); 

所以這使得它如此,它只是返回一個指向字符串數據。然後將其更改爲一個字符串,它傳遞給Marshal.PtrToStringAnsi()

return Marshal.PtrToStringAnsi(GetDLLName()); 

這被裹入清潔度其他功能。

我發現該網頁上的解決方案: http://discuss.fogcreek.com/dotnetquestions/default.asp?cmd=show&ixPost=1108

相關問題