【问题标题】:Difference in implementation of malloc and new. Stack implementation?malloc 和 new 实现的区别。堆栈实现?
【发布时间】:2026-01-02 15:10:01
【问题描述】:

在分配内存时,如果内存不可用,new 运算符会抛出异常。另一方面,malloc 返回 NULL。执行上的差异是什么原因。另外,在静态内存分配上,也就是在栈上,如果内存用完了会不会有异常?

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

【问题讨论】:

    标签: c++ algorithm memory-management


    【解决方案1】:

    可能会增加一些混乱......

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

    注意:new 表达式有一个 no throw 版本

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

    它还负责管理直到将其发布给您。也就是说,如果构造函数抛出异常,那么它会正确处理分配的内存,如果是 new[] 表达式(它构建一个数组),则会调用那些已经构建的对象的析构函数。

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

    请注意,gcc 在编译时引入了拆分堆栈选项,其中包括分配一个最小堆栈,然后按需增长它。这巧妙地回避了可能的堆栈溢出问题,但引入了另一个二进制兼容性问题,因为与不是使用此选项构建的代码的交互可能会变得模糊;我不知道他们究竟打算如何实施。

    【讨论】:

      【解决方案2】:

      C 代码的问题在于您应该检查函数的返回值以确保它们正常工作。但是很多代码都没有检查返回值,结果在你最意想不到的时候就爆炸了。

      在最坏的情况下,它甚至不会立即崩溃,而是继续破坏内存,在错误下游的某个点崩溃。

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

      新的使用适合这种设计。
      如果分配内存失败,则必须显式处理错误。
      没有机会忘记检查 NULL 指针。因此,您不能不小心使用 NULL 指针而弄乱内存。

      另外,在静态内存分配上,也就是在栈上,如果内存用完了会不会有异常?

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

      注意

      如果你#include 那么你可以使用一个不抛出版本的new,当没有剩余内存时返回NULL。除非有特殊需要,否则最好避免。

      【讨论】:

        【解决方案3】:

        为了完整起见,还请记住,您可以使用 nothrow 模拟旧的(非抛出)方法——这尤其适用于代码的性能关键部分:

        // never throws
        char* ptr = new (nothrow) char [1024*1024];
        
        // check pointer for succeeded allocation
        if ( !ptr ) { 
          ... // handle error
        }
        

        【讨论】:

        • 在性能关键代码中,您可能不应该分配大量堆内存。 :-)。并且至少在 C++0x 中,需要默认版本的 new(nothrow) 来调用正常的 new,捕获异常并返回 NULL。 [18.6.1.1]
        【解决方案4】:

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

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

        【讨论】:

        • 实际上有一个new 的无抛出重载,它返回 0 而不是抛出。
        【解决方案5】:

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

        • malloc是分配内存的C路; C中没有例外
        • new 是 C++、面向对象和所有方式; C++ 中也有例外,使用它们更干净


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

        ...但我经常听到(几年前我还在上学时从老师那里)不鼓励在 C++ 中使用 malloc,而 new应改为使用。

        【讨论】: