2013-06-03 74 views
0

大多數我見過的代碼刪除終結/析構函數指針:用C++/CLI互操作管理內存

public ref class CPPObjectWrapper 
{ 
private: 
    CPPObject *_cppObject; 
public: 
    CPPObjectWrapper() 
    { 
     _cppObject = new CPPObject(); 
    } 

    CPPObjectWrapper(IntPtr ^ptr) 
    { 
     _cppObject = ptr->ToPointer(); 
    } 

    ~CPPObjectWrapper() 
    { 
     delete _cppObject; 
     _cppObject = 0; 
    } 

    !CPPObjectWrapper() 
    { 
     if (_cppObject != 0) delete _cppObject; 
    } 

    IntPtr^ GetPointer() 
    { 
     return gcnew IntPtr(_cppObject); 
    } 
} 

我的問題是什麼是標準的做法,如果庫中的包裝確實是這樣的:

void AddObject(CPPObject *cppObject) 
{ 
    // adds to a std::list 
} 

CPPObject* FindObject(/* criteria */) 
{ 
    // return reference to std::list item based on criteria 
} 

如果你的C#封裝器這樣處理:

void AddObject(CPPObjectWrapper ^cppObject) 
{ 
    _internal->addObject(cppObject->GetPointer()->ToPointer()); 
} 

CPPObjectWrapper^ FindObject(/* criteria */) 
{ 
    CPPObject *cppObject = _internal->findObject(/* criteria */); 

    return gcnew CPPObjectWrapper(gcnew IntPtr(cppObjet)); 
} 

你碰到內存ISS因爲你的託管對象不應該刪除指針,因爲它在另一個對象中被引用。返回時也是如此。您是否只需添加功能來告訴您的託管包裝器在所有權轉移後不釋放內存?

+2

在非託管方面,我會使用'std :: shared_ptr'。 –

+2

這在本地代碼中已經非常**了。當本地代碼調用FindObject()時,它應該如何處理返回的指針?它應該調用::運算符刪除或不?如果沒有,當其他代碼刪除它時會發生什麼?當然沒事。您需要先在本機代碼中進行分類。 *也許*你需要在包裝器中添加一個'bool ownsObject;'字段,這樣你就可以在你的析構函數和終結器中做正確的事情。不要將其暴露給託管代碼,它不能解決這個問題。 –

回答

0

處理混合模式項目時的經典情況,您的建議是OK!

如果在另一個非包裝對象中使用同一個對象,那麼在構造函數中設置一個布爾值,告訴它不要銷燬指針是有意義的。 理想的情況是每個對象都被包裝起來,並且銷燬將由CLR完成。

你可以使用一個通用的基類(使用你已經有的代碼),默認情況下由子類設置bool。你保證有這個功能多次。另一個技巧是從CLR析構函數(!)調用虛擬OnFinalize()方法,該方法可以在子類中執行特殊操作,如調用本地庫提供的一些特殊的免費函數。