2013-06-03 2 views
0

Большая часть кода я видел удаляет указатель в финализатора/деструктор:управление памятью с C++/CLI Interop

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 
} 

Если с # обертка делает это:

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

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

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

Вы бежите в ИСС памяти ue, потому что ваш управляемый объект не должен удалять указатель, потому что он ссылается на другой объект. То же самое верно при возвращении. Вы просто добавили бы функциональность, чтобы сообщить управляемой оболочке не освобождать память при передаче прав собственности?

+2

На неуправляемой стороне я бы использовал 'std :: shared_ptr'. –

+2

Это уже ** очень ** мутный в собственном коде. Когда собственный код вызывает FindObject(), что он должен делать с возвращенным указателем? Должен ли он вызвать :: operator delete или нет? Если нет, что происходит, когда какой-либо другой код удаляет его? Ничего хорошего, конечно. Сначала вам нужно сначала разобрать это в собственном коде. И * возможно * вам нужно добавить поле 'bool ownsObject;' в оболочку, чтобы вы могли сделать правильную вещь в своем деструкторе и финализаторе. Не подвергайте это управляемому коду, он не может решить эту проблему. –

ответ

0

Классическая ситуация при работе с проектами смешанного режима, и ваше предложение в порядке!

Было бы разумно иметь bool в конструкторе, который говорит ему не уничтожать указатель, если тот же объект используется в другом не обернутом предметом. Идеальный случай заключается в том, что каждый объект был обернут, а уничтожение будет выполнено CLR.

Из этого можно сделать общий базовый класс (используя код, который у вас уже есть), установив bool по умолчанию подклассом. Вы гарантированно получите эту функцию много раз. Еще один совет: иметь виртуальный метод OnFinalize(), который вызывается из деструктора CLR (!), Который может выполнять специальные операции в подклассе, например, вызывать некоторую специальную свободную функцию, предоставляемую собственной библиотекой.

Смежные вопросы