繁体   English   中英

互操作c ++时释放的已分配内存

[英]free allocated memory when interoping c++

填充包含字符串的stuct数组,我测试了一个发现,在c#中它通过指针执行得更快:

struct name{
    int intv;
    IntPtr strv;
}

当通过GetPacksPtr()实现时:(请参见下面的代码/签名),这就是我的编码方式,并且不确定我是否做对了...

说ArrL = 10,000

        DataPack* DataPackArr;
        List<DataPack> DataPackLst = new List<DataPack>(ArrL);
        GetPacksPtr(ArrL, &DataPackArr);

        DataPack* CurrentPack = DataPackArr;
        for (int i = 0; i < ArrL; i++, CurrentPack++)
        {
            DataPackLst.Add(new DataPack() { strv = CurrentPack->strv, intv = CurrentPack->intv });
        }

我在哪里可以释放分配的内存,因为__stdcall定义了非托管代码必须释放内存,但是谁是所有者(“契约”)……这令人困惑,我试图以最低的性能命中率来释放分配。

C ++

extern "C" __declspec(dllexport) void __stdcall GetPacksPtr(int size, DataPack** DpArrPtr )
{

    *DpArrPtr = (DataPack*)CoTaskMemAlloc( size * sizeof( DataPack ));
    DataPack CurPackPtr = *DpArrPtr;
    char aStr[]= "abcdefgHi";
    for ( int i = 0; i < size; i++,CurPackPtr++ )
    {

        CurPackPtr->IntVal=i;
        CurPackPtr->buffer = (char*)malloc(sizeof(aStr));
        strcpy(CurPackPtr->buffer, aStr);
    }


}

C#

    [DllImport("exported.dll", CallingConvention = CallingConvention.StdCall), SuppressUnmanagedCodeSecurity]
    public static extern void GetPacksPtr(int RaySize, DataPack** DataPackArr);

是的,当你手动分配内存,它是当然的更快,这是很常见的,你需要另外一个(这部分我不知道该说些什么,因为你的一切混合) 功能这样的

__declspec(dllexport) void __stdcall FreePacksPtr(int size, DataPack *DpArrPtr)
{
    for (size_t i = 0 ; i < size ; ++i)
        free(DpArrPtr[i].buffer);
    CoTaskMemFree(DpArrPtr);
}

然后,在C#中,只要不再需要指针,就调用FreePacksPtr()

注意 :事实上,您需要extern "C"意味着C#代码期望从dll加载确切的符号,似乎您必须指示microsoft编译器编译c代码而不是c ++,我不是100%当然可以,但是Microsoft编译器将这些混合在一起。

当您分配非托管内存时,您必须释放它-但是没有关于谁负责释放的规则。

在不受管理的世界中,通常的策略是为每个需要释放的资源都拥有一个“所有者”,这种所有权是释放对象的责任。

如果函数A分配了一块内存,然后将指针传递给函数B,则有两种选择:

  1. A仍然是所有者,完成后将释放内存,B不必处理释放内存的问题,但也无法保存指针供以后使用,因为A可以随时将其释放

  2. 所有权从A转移到B,现在B负责释放,并且B返回后A不能对指针执行任何操作,因为B可以随时将其释放

请注意,函数原型中没有任何东西可以表示所有权,所有这些都是通过程序员A和程序员B之间的协议达成的(通常称为“按合同”)

现在,要使事情变得更复杂,可以从中分配许多内存块(称为“堆”),释放时,需要释放到用于分配的同一堆中。

Windows管理着几个堆,.net Marshal类具有将内存释放到其中的方法。

malloc使用的堆不是其中之一,必须通过在与malloc相同的dll中调用free来释放malloc分配的内存。

最后但并非最不重要的一点是,分配和释放内存是您在非托管代码中可以执行的最慢的操作之一,如果您执行了很多操作,则会遇到诸如内存碎片和引用局部性之类的麻烦(此答案足够长,而没有进入他们)

分配和释放策略对非托管代码的性能有巨大影响-这不会对您的性能产​​生最小的影响。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM