Утечка памяти - освободить и удалить

IFSUPCUTILSize* size = NULL;
CoCreateInstance(CLSID_UTILSize, NULL, CLSCTX_INPROC_SERVER, IID_IFSUPCUTILSize,    reinterpret_cast<void**>(&size));

if (size != NULL){
size->Release();
size = NULL;
}
delete size;

Нужно ли мне «удалить размер» в приведенном выше коде? Если я включу «удалить размер», будет ли у меня утечка памяти, потому что я не использовал New. Или внутри вызова CoCreateInsatnce есть New. Я построил это с помощью VC++ 6.


person dysonfree    schedule 25.08.2011    source источник
comment
Возможно, вы захотите перейти на более новую версию Visual Studio.   -  person GManNickG    schedule 26.08.2011


Ответы (5)


COM-интерфейсы имеют подсчет ссылок. CoCreateInstance() возвращает указатель интерфейса на COM-объект, счетчик ссылок которого уже увеличен. Вызов Release() уменьшает счетчик ссылок. Когда счетчик ссылок падает до нуля, COM-объект автоматически освобождается. НЕ вызывайте delete для указателя COM-интерфейса! Всегда используйте только Release().

person Remy Lebeau    schedule 25.08.2011
comment
Спасибо. Хорошее образование для меня. ОП - person dysonfree; 26.08.2011

С точки зрения С++ то, что вы делаете, в порядке. Вызов удаления для нулевого указателя не является операцией. Однако это необязательно.

С точки зрения VC++6 я не могу сказать, что он заведомо не соответствует требованиям. Я не могу представить, почему это может быть проблемой. Но опять же, это, конечно, ненужно.

Определенно не вызывайте удаление для этого указателя, пока он не будет установлен в NULL. Вы не выделяли с помощью нового, поэтому не вызывайте удаление. Управление ресурсами здесь осуществляется функциями COM.

person Benjamin Lindley    schedule 25.08.2011

Никогда не пытайтесь использовать delete для выпуска COM-серверов, реализованных другим модулем (это ваш случай).

  1. Вы не всегда знаете, написан ли этот сервер на C++. Выполнение delete для объекта, отличного от C++, является неопределенным поведением.
  2. Даже если сервер написан на C++, вы не знаете, в какой куче он был выделен и будет ли delete правильно освобождать память или вызовет неопределенное поведение.
  3. Вы вызываете delete для указателя интерфейса, который объявлен как не имеющий виртуального деструктора - это неопределенное поведение.
  4. Вы не всегда знаете, был ли вам предоставлен реальный объект или прокси. Выполнение delete на прокси-сервере — поведение undefined.
  5. После того, как вы вызвали Release(), объект, возможно, уже самоуничтожился, и повторное выполнение delete является неопределенным поведением.
  6. Кто-то из третьих лиц мог завладеть объектом — например, некоторый экземпляр глобального указателя мог быть установлен на ваш объект. Если вы delete, эти другие указатели станут висящими, что, вероятно, позже приведет к неопределенному поведению.

Итог: никогда не используйте delete в этом случае. Вызовите Release(), чтобы освободить объект, и этого будет достаточно.

person sharptooth    schedule 26.08.2011

Если я включу «удалить размер», будет ли у меня утечка памяти, потому что я не использовал New.

Как правило, вы не получите утечки памяти, вызвав delete. Вы можете и много раз будете сталкиваться с повреждением памяти. Они очень разные: утечка памяти означает, что ваша программа удерживает память, которую она на самом деле не использует, со временем программа может выйти из строя, если утечка памяти продолжит расти; повреждение памяти означает, что вы каким-то образом уничтожили важные бухгалтерские структуры в памяти, и, вероятно, очень скоро произойдет сбой (по крайней мере, вы должны надеяться на сбой, альтернатива хуже). Одной из очень распространенных причин повреждения памяти является освобождение памяти с неправильным рутина, особенно в Windows (традиция переопределять malloc и free в UNIX, поэтому системы UNIX часто делают все возможное, чтобы убедиться, что это возможно).

Или внутри вызова CoCreateInstance есть New?

Все, что находится внутри CoCreateInstance, должно быть обработано Release(). По крайней мере, вы никогда не должны освобождать память только потому, что у вас есть указатель. Вам нужно знать, как была выделена память, чтобы правильно ее освободить.

person Max Lybbert    schedule 25.08.2011

Я предполагаю, что size->Release() освобождает ресурсы ОС (дескрипторы файлов и т. д.). Поэтому поместите размер удаления сразу после того, как установите размер равным нулю.

person Ed Heal    schedule 25.08.2011
comment
Он не выделял с помощью new, он не должен вызывать для него удаление. - person Benjamin Lindley; 26.08.2011
comment
Я унаследовал код. Я проверяю остальную часть кода. Указатели освобождаются и обнуляются в следующей строке. Я добавил удалить себя по незнанию. Я думаю, нет никакого вреда для совместимого компилятора. Но MS, я лучше удалю. Я согласен, что мне не нужно удалять, если у меня нет New. Спасибо. Этот форум великолепен. - person dysonfree; 26.08.2011