malloc和new的实现差异。堆栈实现?

时间:2011-02-26 10:06:15

标签: c++ algorithm memory-management

在分配内存时,如果内存不可用,则new运算符会抛出异常。另一方面,malloc返回NULL。实施差异的原因是什么?另外,在静态内存分配上,即在堆栈上,如果我们的内存不足会有例外吗?

我已经浏览了What is the difference between new/delete and malloc/free?链接  但是没有得到关于两者实施差异的答案

5 个答案:

答案 0 :(得分:5)

C代码的问题是你应该检查函数的返回值以确保它们正常工作。但是很多代码都是在没有检查返回值的情况下编写的,因此当你最不期望的时候会很好地爆炸。

在最糟糕的情况下,它甚至不会立即崩溃,但会继续破坏内存在错误的下游几英里处崩溃。

因此,在C ++中,异常就诞生了 现在当出现错误时代码不会继续(因此没有内存损坏)但是展开堆栈(可能会强制应用程序退出)。如果您可以处理该问题,则必须在继续之前显式添加代码以处理该情况。这样你就不会忘记不检查错误情况;您要么检查它,要么应用程序将退出。

使用新设计符合此设计 如果您未能分配内存,则必须明确处理错误 没有机会忘记检查NULL指针。因此,你不能意外地使用NULL指针去搞乱内存。

  

另外,在静态内存分配上,即在堆栈上,如果内存不足会有异常吗?

不幸的是你不能依赖这个。
它是实现定义堆栈溢出时发生的事情。在许多系统上,甚至无法检测到导致内存损坏并最终可能导致崩溃的情况。

注意

如果你#include< new>然后有一个你可以使用的无抛出版本,当没有内存时返回NULL。除非有一些特殊需要,否则最好避免使用。

答案 1 :(得分:2)

malloc不能抛出异常,因为这会破坏与C的兼容性。new抛出异常,因为这是C ++中发出错误信号的首选方式。

据我所知,在早期版本的C ++中,new确实在失败时返回0,

答案 2 :(得分:1)

我认为,一个重要的区别在于:

  • malloc是分配记忆的C方式;并且在C
  • 中没有例外
  • new是C ++,面向对象的所有方式;在C ++中有例外,使用它们是更干净


为什么要将malloc保留在C ++中?我想这是因为C ++编译器也可以使用C代码......

...但我经常听到(来自老师,几年前我还在学校)不鼓励在C ++中使用malloc,{应该使用{1}}。

答案 3 :(得分:1)

冒着可能增加一些困惑的风险......

  • malloc是常规的C函数。因为它是C,它只能通过适合C程序的方式发出错误信号:使用返回值,指针传递的参数或全局变量(如errno)。
  • new引入了一个C ++表达式,它调用operator new来获取内存,然后构造该对象。 operator new或构造函数可能会抛出。

注意:new表达式的无抛出版

大多数operator new通常以malloc的形式实现,但正如我所指出的那样,new表达式不仅仅是获取内存,因为它还构建了对象

它还负责管理直到它发布给你。也就是说,如果构造函数抛出,则它会正确处理已分配的内存,并且在new[]表达式(构建数组)的情况下,调用已构建的那些对象的析构函数。

关于堆栈溢出:它取决于您的编译器和操作系统。操作系统可能会注意到该问题并发出错误信号,编译器可能会检查等...

请注意,gcc引入了split-stack选项进行编译,其中包括分配最小堆栈然后按需增长。这巧妙地回避了可能的堆栈溢出问题,但引入了另一个二进制兼容性问题,因为与未使用此选项构建的代码的交互可能会变得模糊;我不知道他们计划如何实现这一目标。

答案 4 :(得分:0)

为了完整起见,请记住,您可以使用nothrow模拟旧的(非投掷)方法 - 这特别适用于代码的性能关键部分:

// never throws
char* ptr = new (nothrow) char [1024*1024];

// check pointer for succeeded allocation
if ( !ptr ) { 
  ... // handle error
}