为什么我们不能释放()由new分配的内存?

时间:2011-04-22 03:45:10

标签: c++ memory-management new-operator

我知道free()不会调用析构函数,但除了成员变量不会被正确破坏之外还会引起什么呢?

此外,如果我们delete指针由malloc分配?

,该怎么办?

6 个答案:

答案 0 :(得分:11)

答案 1 :(得分:8)

  

我知道free()不会调用析构函数

这是足够的理由不这样做。

此外,不要求C ++实现甚至为mallocnew使用相同的内存区域,因此可能是因为你试图从一个完全不同的领域释放内存,什么几乎肯定是致命的。

答案 2 :(得分:4)

很多要点:

  • 这是一种未定义的行为,因而具有内在的风险,随时都可能发生变化或破损,而且完全没有理由。
  • (如你所知)delete调用析构函数而free没有...你可能有一些POD类型而不关心,但是其他人很容易添加说{{1} 1}}对于那种类型而没有意识到其内容存在奇怪的限制。
  • 如果您string并忘记使用placement malloc在其中构造对象,则调用一个成员函数,就好像该对象存在一样(包括调用析构函数的new),成员函数可以尝试使用带有垃圾值的指针进行操作
  • deletenew可能会从不同的堆中获取记忆。
  • 即使如果 malloc调用new来获取内存,malloc / new之间也可能没有1:1的对应关系和潜在的delete / malloc行为。
    • e.g。 free可能有额外的逻辑,例如小对象优化,这些逻辑已被证明对典型的​​C ++程序有益,但对典型的C程序有害。
  • 有人可能会重载new,或链接到new / malloc / realloc的调试版本,如果您不使用这些功能,其中任何一个都可能会中断正常。
  • 像ValGrind,Purify和Insure这样的工具将无法区分故意的可疑和意外。
  • 对于数组,free调用所有析构函数而delete[]不会,但堆内存通常也有一个数组大小的计数器(对于32位VC ++ 2005)例如,发布版本,数组大小在free()明显返回指针值之前的4个字节中。这个额外值可能是也可能不是POD类型(不适用于VC ++ 2005),但是如果是new[]肯定不会指望它。并非所有堆实现都允许你释放一个已经从free()返回的值转移的指针。

答案 3 :(得分:2)

一个重要的区别是new和delete也调用了对象的构造函数和析构函数。因此,您可能会遇到意外行为。这是我认为最重要的事情。

答案 4 :(得分:2)

因为它可能不是相同的分配器,这可能导致奇怪的,不可预测的行为。另外,你根本不应该使用malloc / free,并且避免在没有必要的情况下使用new / delete。

答案 5 :(得分:1)

这完全取决于实现 - 可以编写一个实际工作正常的实现。但是不能保证内存池new分配来自free()想要返回内存的同一个池。想象一下,malloc()new在每个已分配块的开头使用几个字节的额外内存来指定块的大小。此外,假设malloc()new对此信息使用不同的格式 - 例如,malloc()使用字节数,但new使用4字节的数字长话(只是一个例子)。现在,如果您使用malloc()进行分配并使用delete免费分配,那么信息delete预计无效,并且您最终会遇到损坏的堆。