2015-04-01 55 views
1

我一直在我們的應用程序之一調試堆腐敗異常。它剛開始發生在上個月(2015年3月),代碼沒有改變。 windbg將其縮小爲一些代碼,我們正在使用pinvoke從c#調用zlib函數。csharp zlib zlibversion pinvoke導致隨機崩潰(堆損壞)

的代碼片段是:

public class Info 
{ 

    [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] 
    private static extern string zlibVersion(); 


    public static string Version { get { return zlibVersion(); } } 
} 

它看起來像這樣的代碼是從zlib.net源\的contrib \ dotzlib \ DotZLib \ DotZlib.cs其是dotnet的包裝器ZLIB.DLL。

問題:任何想法爲什麼這會導致堆腐敗? dotnet pinvoke有問題嗎?我想很多其他應用程序可能會使用這個相同的包裝。然而,我並沒有發現其他人在互聯網上抱怨這一點。

編輯1 - 下面是從zlib的源(zlib.h)的非託管接口:

ZEXTERN const char * ZEXPORT zlibVersion OF((void)); 
+0

現在什麼都ZEXTERN,ZEXPORT和的定義是什麼? – 2015-04-01 19:32:43

回答

2

最有可能的解釋是,這個函數返回的C字符串是靜態分配的。因此不能由調用者釋放,這是p/invoke編組對你的代碼的處理。它通過將C字符串傳遞給CoTaskMemFree來完成此操作。

所以你需要停止發生。通過手動編組返回值來做到這一點。

[DllImport("ZLIB1.dll", CallingConvention = CallingConvention.Cdecl)] 
private static extern IntPtr zlibVersion(); 

public static string Version 
{ 
    get 
    { 
     return Marshal.PtrToStringAnsi(zlibVersion()); 
    } 
} 
+0

謝謝。這似乎是在我們的自動化測試中修復崩潰。我會讓zlib人知道。 – ujjb 2015-04-01 19:53:55

+0

我發現這也是有更多的信息。仍然不確定爲什麼它剛剛開始崩潰。有關的代碼在很多年裏都沒有改變過。 http://stackoverflow.com/questions/6300093/why-cant-i-return-a-char-string-from-c-to-c-sharp-in-a-release-build – ujjb 2015-04-01 20:03:49

+1

操作系統更新可以解釋行爲的改變。 FWIW,這一個更好:http://stackoverflow.com/questions/370079/pinvoke-for-c-function-that-returns-char/370519#370519但沒有比我的答案更多的信息。這就是全部。字符串返回值假定已經在COM堆上動態分配,並且預計將由調用者解除分配。 – 2015-04-01 20:06:21