用new创建的C++对象,用free()销毁; 这有多糟糕?

Dmi*_*tri 37 c++ memory-management

我正在修改一个相对较大的C++程序,遗憾的是,我之前是否有人使用过C或C++语法(这是在大学的电气工程系,而且我们的EE总是试图用C代替一切)并不总是很清楚,不幸的是,在这种情况下,人们实际上可以逃脱它).

但是,如果有人创建了一个对象:

Packet* thePacket = new Packet();

是否被摧毁delete thePacket;或是否重要free(thePacket);

我意识到删除调用析构函数而free()没有,但Packet没有析构函数.我在这里陷入了记忆管理沼泽的可怕时间,我想这可能是许多问题之一.

sre*_*ean 53

是的,这很重要.

对于使用new你获得的内存必须使用delete.

对于使用malloc你获得的内存必须使用free.

new 并且malloc可以在内部使用不同的数据结构来跟踪它分配内存的内容和位置.因此,为了释放内存,您必须调用知道这些数据结构的相应函数.然而,在一段代码中混合这两种类型的内存分配通常是个坏主意.

  • @Dmitri,valgrind可以帮助您找到不匹配. (2认同)
  • 只要您始终使用相应的删除/释放方法,我不认为将 new 和 malloc 混合使用是什么坏主意。事实上,在代码中使用 malloc/realloc/free 有几个原因,否则使用 new/delete(即管理应该重新分配的内部缓冲区等)。有人甚至可以使用其他堆管理功能(即 Windows 系统上的 HeapAlloc 和朋友)。或者编写一个自己的内存池。为什么不混合呢? (2认同)

Ken*_*oom 28

如果你打电话free(),析构函数不会被调用.

此外,无法保证newfree在同一堆上运行.

您还可以覆盖newdelete特定操作特定类.如果你这样做,但是调用free()而不是自定义delete,那么你会错过你写的任何特殊行为delete.(但你可能不会问这个问题,如果你这样做了,因为你知道你错过了什么行为......)


Omn*_*ous 6

Packet有一个析构函数,即使你没有明确声明一个.它有一个默认的析构函数.默认的析构函数可能实际上并没有做太多,但你不能指望这种情况.这取决于编译器的功能.

new并且malloc也可能有完全不同的实现.例如,总是在上下文中调用delete,在上下文中,delete具有关于它在编译时删除的数据结构大小的完美信息. free没有这种奢侈.new正在使用的分配器可能不会在内存区域的开头存储字节,说明它占用了多少字节.这将导致free完全做错事,并在释放分配的内容时使程序崩溃new.

就个人而言,如果让人们做正确的事情或自己修复代码是完全不可能的,我会声明我自己的全局operator new调用malloc所以然后free肯定不会崩溃,即使它仍然不会调用析构函数并且通常非常难看.


Chu*_*dad 5

简而言之,它与未定义的行为一样糟糕。

这是不言自明的。

C 标准 ($7.20.3.2/2) - “free 函数导致 ptr 指向的空间被释放,即可供进一步分配。如果 ptr 是空指针,则不会发生任何操作。否则,如果参数与 calloc、malloc 或 realloc 函数先前返回的指针不匹配,或者如果空间已通过调用 free 或 realloc 释放,则行为未定义。”