微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Microsoft 默认封送处理行为的双重免费问题

如何解决Microsoft 默认封送处理行为的双重免费问题

根据微软"Default Marshaling Behavior"

引用:

例如,从 C++ DLL 调用以下非托管方法不会自动释放任何内存。 非托管签名

C++


BSTR Methodone (BSTR b) {  
   return b;  
}  

但是,如果将方法定义为平台调用原型,将每个 BSTR 类型替换为 String 类型,并调用 Methodone,公共语言运行时将尝试释放 b 两次。您可以使用 IntPtr 类型而不是 String 类型来更改封送处理行为。

已阅读此文档几次,试图弄清楚发生了什么卧底,我确实尝试对示例进行编码以重现错误

C++ dll:


    #include <Windows.h>
    
    
    extern "C"
    {
        __declspec(dllexport) BSTR __cdecl test_returnself(BSTR b)
        {
            return b;
        }
    }

C# 签名和调用

[DllImport("Test_Csharp_Marshal.dll",CallingConvention =CallingConvention.Cdecl)]
extern static string test_returnself(string b);
...
string asd = "hello world";
string kksk = test_returnself(asd);

好吧,问题是,这个程序运行得很好,退出代码为 0

问题来了:

看完这篇文档,我做了一个“猜测”,说服自己理解了marshaller的机制:

托管端发送输入字符串并获取返回字符串。然而,它们实际上引用了同一个对象,因此 CLR 尝试释放 b 两次。

但是在阅读更多文档和 question 之后。

我觉得它更像是对输入进行复制和对返回值进行复制,而返回和输入实际上是两个对象。那么这个“双自由对象”问题是如何发生的呢?

此外,在这question

他确实遇到了那个问题,我也猜测了原因:

函数返回的字符实际上是由 Sysalloc 等方法分配的,因此 CLR 可以自动释放这种类型,而在非托管端,它有自己的垃圾收集器,因此可以释放两次。

如果我错了,请纠正我,因为我确实认为它不正确。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。