簡體   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