2015-04-01 53 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