csharp zlib zlibversion pinvoke 导致随机崩溃(堆损坏)

csharp zlib zlibversion pinvoke causes random crash (heap corruption)

我一直在调试我们的一个应用程序中的堆损坏异常。它是上个月(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));

最可能的解释是,此函数 returned 的 C 字符串是静态分配的。因此,调用者不得解除分配,这是 p/invoke 编组器对您的代码所做的。它通过将 C 字符串传递给 CoTaskMemFree 来完成此操作。

所以你需要阻止这种情况发生。通过手动封送 return 值来做到这一点。

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

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