内存泄漏 - 释放和删除

5
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;

在上述代码中,我是否需要使用“delete size”? 如果我包括“delete size”,由于我没有使用New,会导致内存泄漏吗? 还是在调用CoCreateInstance时有一个New。 我使用VC++ 6构建了这个代码。

2
你可能想要升级到更高版本的Visual Studio。 - GManNickG
5个回答

11

COM接口是有引用计数的。调用CoCreateInstance()会返回一个已经增加了引用计数的COM对象接口指针。 调用Release()会减少引用计数。 当引用计数降至零时,COM对象会自动释放自己。不要在COM接口指针上调用delete!只使用Release()


谢谢。对我来说是很好的教育。OP - dysonfree

4

从C++的角度来看,你所做的是正确的。对空指针进行删除操作是不起作用的。然而,这是不必要的。

从VC++6 的角度来看,我不能确定,因为它非常不兼容。我无法想象为什么会有问题。但是同样地,这肯定是不必要的。

绝对不要在将指针设置为NULL之前对其进行删除操作。 你没有使用new进行分配,因此不要调用delete。这里的资源管理由COM函数处理。


1

永远不要尝试使用delete释放由另一个模块实现的COM服务器(这是您的情况)。

  1. 您并不总是知道该服务器是否是用C++编写的。在非C++对象上执行delete是未定义的行为。
  2. 即使服务器是用C++编写的,您也不知道它是在哪个堆上分配的,以及delete是否会正确地释放内存或触发未定义的行为。
  3. 您调用了声明为没有虚析构函数的接口指针上的delete - 这是未定义的行为。
  4. 您并不总是知道您是否已经被提供了一个真正的对象还是代理。在代理上执行delete是未定义的行为。
  5. 一旦您调用了Release(),对象可能已经自删除,再次执行delete是未定义的行为。
  6. 某些第三方可能已经拥有该对象的所有权 - 例如,某些全局指针实例可能已经设置为您的对象。如果您delete这些其他指针将变得悬空,并且这很可能会导致以后的未定义行为。
底线:在这种情况下永远不要使用delete。调用Release()来释放对象的所有权就足够了。

0
如果我包含“delete size”,因为我没有使用New,那么我会有内存泄漏吗?
通常情况下,调用delete不会导致内存泄漏。但是,您可能会遇到许多次内存损坏。这两者非常不同:内存泄漏意味着您的程序占用了它实际上并未使用的内存,随着时间的推移,如果泄漏的内存继续增长,程序可能会崩溃;内存损坏意味着您以某种方式破坏了内存中的重要簿记结构,并且很快就会崩溃(至少您应该希望出现崩溃,否则后果更糟)。内存损坏的一个非常常见的原因是使用错误的例程释放内存,特别是在Windows上(在UNIX上重新定义malloc和free已经成为一种传统,因此UNIX系统经常尽力确保可以这样做)。
或者在CoCreateInstance的调用中是否有New?

CoCreateInstance 内部的任何内容都应该由 Release() 处理。至少,您不应该仅因为有一个指针就释放内存。您需要知道内存是如何分配的,才能正确地释放它。


-1

我假设 size->Release() 释放了操作系统资源(文件句柄等)。因此,在将 size 设置为 null 之前,立即执行 delete size。


3
他没有使用new分配内存,所以不应该调用delete来释放它。 - Benjamin Lindley
我继承了这段代码。我检查了其余的代码。指针在下一行被释放并设置为null。由于无知,我自己添加了delete。我猜对于一个合规的编译器来说没有什么害处。但是对于微软来说,最好将其删除。我同意如果我没有New的话就不需要删除。谢谢,这个论坛很棒。 - dysonfree

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接