在分配内存时,如果内存不可用,则new运算符会抛出异常。另一方面,malloc返回NULL。实施差异的原因是什么?另外,在静态内存分配上,即在堆栈上,如果我们的内存不足会有例外吗?
我已经浏览了What is the difference between new/delete and malloc/free?链接 但是没有得到关于两者实施差异的答案
答案 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
}