【问题标题】:C# calling C++ method that returns a pointer. Explain memory managementC# 调用返回指针的 C++ 方法。解释内存管理
【发布时间】:2010-10-26 22:49:34
【问题描述】:

有人可以在下面的“Main”中的 2 个 C# 行中从低级别/内存管理的角度解释到底发生了什么吗?

C++ 代码(非托管):

    #define DLLEXPORT extern "C" __declspec(dllexport)

    DLLEXPORT MyClass* MyClass_MyClass()
    {
        return new MyClass();
    }
    DLLEXPORT void MyClass_setName(MyClass* myClass, const char* name)
    { 
        myClass->setName(name);
    }

MyClass::MyClass()
{
    _name.clear();
}
void MyClass::setName(const char* name)
{
    _name.setCString(name, NAME_MAX_BYTES);
}

C#代码:

        [DllImport(@"lib.dll")]
        private static extern IntPtr MyClass_MyClass();
        [DllImport(@"lib.dll")]
        public static extern void MyClass_setName(
                    IntPtr myClass,
                    [System.Runtime.InteropServices.InAttribute()]
                    [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)]
                    string name);

        public static void Main(string[] args)
        {
            var myClass = MyClass_MyClass();
            MyClass_setName(myClass , "Test Name");
        }

具体来说,我想知道.NET 是如何知道要为“myClass”分配多少空间的?它必须在后台执行某种“Marshal.AllocHGlobal(SIZE)”,对吗?如果需要更多空间会发生什么(我设置了名称?)?此外,是否存在垃圾收集和移动内存以及弄乱我的“IntPtr myClass”的风险?

【问题讨论】:

    标签: c# c++ memory-management pinvoke intptr


    【解决方案1】:

    .NET 对MyClass 类型一无所知,它只存储一个指向它的指针。指针的大小始终是已知且固定的——32 位进程为 4 个字节,64 位进程为 8 个字节。在这种特殊情况下,所有内存分配和管理都发生在此处的非托管 C++ 代码中:

    return new MyClass();
    

    这里:

    myClass->setName(name);
    

    由这个 C++ DLL 决定如何分配/释放/管理内存,C# 代码只会调用这个 DLL 的导入函数。

    不会对您的非托管对象执行垃圾回收,您需要提供额外的(非托管)方法来释放它以避免内存泄漏。

    【讨论】:

      【解决方案2】:

      如果 c++ 代码不受管理,.net 不会分配 IntPtr 之外的任何内容。它是由 c++ 代码分配的。

      这意味着唯一的垃圾收集将在该 IntPtr 上完成。由于它很小,垃圾收集器可能需要很长时间才能决定清理它。

      这意味着即使您的 C++ 代码自行清理得很好,也可能需要很长时间才能真正进行清理。 C++ 代码可能使用了大量内存,但它对 .net 是不可见的,因此它不会优先清理“更大”的 .net 对象。

      【讨论】:

        猜你喜欢
        • 2010-11-14
        • 1970-01-01
        • 2013-08-19
        • 2023-03-28
        • 2015-05-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-24
        相关资源
        最近更新 更多