我一直在我们的一个应用程序中调试堆损坏异常。它刚刚在上个月(2015年3月)开始发生,代码没有改变。 windbg将它缩小到一些代码,我们使用pinvoke从c#调用zlib函数。
代码段是:
public class Info
{
[DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]
private static extern string zlibVersion();
public static string Version { get { return zlibVersion(); } }
}
看起来这段代码来自zlib.net source \ contrib \ dotzlib \ DotZLib \ DotZlib.cs,它是zlib.dll的dotnet包装。
问题:知道为什么会导致堆损坏吗? dotnet pinvoke有问题吗?我认为很多其他应用程序可能正在使用这个相同的包装器。但是,我没有发现其他人在互联网上抱怨这一点。
编辑1 - 这是来自zlib源(zlib.h)的非托管接口:
ZEXTERN const char * ZEXPORT zlibVersion OF((void));
答案 0 :(得分:2)
最可能的解释是此函数返回的C字符串是静态分配的。因此,调用者不能释放它,这就是p / invoke marshaller对你的代码所做的事情。它通过将C字符串传递给CoTaskMemFree
来完成此操作。
所以你需要阻止这种情况发生。通过手动编组返回值来做到这一点。
[DllImport("ZLIB1.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr zlibVersion();
public static string Version
{
get
{
return Marshal.PtrToStringAnsi(zlibVersion());
}
}