【问题标题】:What happens if my app is out of memory?如果我的应用程序内存不足怎么办?
【发布时间】:2009-04-25 13:41:45
【问题描述】:

如果我的应用程序在我调用 new() 时内存不足,我会得到异常,而 malloc() 我会得到 0 指针。

但是如果我调用带有一些局部变量的方法呢?它们也占用内存。有没有办法为“正常”变量保留内存?这样即使 new() 抛出异常,我也可以捕获它,修复内容并仍然像往常一样调用方法。

【问题讨论】:

    标签: c++ memory-management


    【解决方案1】:

    您的数据以以下三种方式之一分配:

    • 静态分配的数据(静态成员或全局变量)是在应用启动时分配的,这意味着它们不会成为真正的问题。
    • 堆栈分配的数据在堆栈上分配(惊喜!)堆栈是为局部变量和函数堆栈帧留出的内存区域。如果你在那里的空间用完了,那会发生什么是不确定的。一些实现可能会检测到它并给您访问冲突/分段错误,而其他实现只会让您覆盖堆数据。无论如何,没有办法检测到这一点,因为一般来说,没有办法处理它。如果你的堆栈空间用完了,你就无能为力了。你甚至不能调用函数,因为这会占用堆栈空间。
    • 堆分配的内存是您在调用 new/malloc 时使用的内存。在这里,您有一种机制来检测内存不足的情况,因为您可能能够处理它。 (而不是分配 200mb,您也许可以用 100mb 凑合,然后在中途交换数据)

    你通常不应该用完堆栈空间,除非你执行一些繁重的递归。

    【讨论】:

      【解决方案2】:

      C++ 语言不提供任何机制来为局部变量保留内存。您的特定 C++ 实现和/或操作系统可能会提供一些增加总堆栈大小的方法,但这通常不是必需的。

      还请注意,如果对 new 的调用确实失败了,您实际上几乎无法从中恢复。许多人(包括我)不再费心检查新的故障。

      【讨论】:

      • 重新失败:一个问题是异常处理程序/日志记录逻辑可能会尝试在堆上分配空间——这当然会失败!为了降低这种“嵌套错误”的可能性,您可以在程序开始时分配一个小的“降落伞”(例如 2kb)并在出现新故障时将其删除。
      • (当然,大多数人都知道不要在内存不足时调用的错误处理程序中直接调用 new...但是可以间接调用 new,例如通过 std::vector ,而且这种可能性更难消除。)
      【解决方案3】:

      编译器知道每个堆栈需要多少内存。但是,足够多的堆栈(由递归引起)会使您的程序崩溃——可能没有其他方法可以解决此问题。

      该标准有一个有趣的附件,称为实施数量。这是非规范性(信息性),因此不应被视为绝对真理,而是为您提供一个公平的想法。

      【讨论】:

      • 但它会为至少一些堆栈保留足够的内存吗?
      • 是的,可能。自尊的编译器也将尽其所知(并在您的帮助下)尝试修复尾递归和其他暴行。检查这一点的一个好方法是编写一个斐波那契并将其称为 600 之类的值。
      • 当您说“每个堆栈的内存”时,您指的是编译器知道的堆栈帧。程序所需的总堆栈大小取决于代码路径,因此编译器通常很难(如果不是不可能)预测。通常,程序员会指出程序(或线程,就此而言)所需的堆栈大小
      • @Jeff:我的意思是堆栈管理内存+变量。
      • 一般只有一个栈,用于内务和局部变量。 (所有这些都适合每个函数调用的一个堆栈帧)。通常,堆栈大小是固定的(1mb 是常见的默认值,afaik)
      【解决方案4】:

      New 从堆中分配内存,但本地变量通常位于堆栈上 - 这可能会溢出,但可能性较小,具体取决于您的平台。你能提供更多细节吗?

      【讨论】:

      • 可以说我调用 new 或 malloc 直到它们失败,因为没有更多的内存了。然后我调用一些方法,让我们说 100 个局部整数变量会发生什么?我需要该方法照常工作。
      • 堆和栈是两个独立的内存区域——通常不相关。你可以有一个 2Mb 的堆和一个 1Mb 的堆栈。
      • @Jeff:我不认为它在现代保护模式操作系统中是一样的,但是在 DOS 时代,堆栈和堆可能会发生冲突——基本上,堆栈是从内存顶部向下增长的,堆长大了。
      • @j_random_hacker:同意——“回到过去”——我们可能会意外或故意将它们一起运行。现在的孩子们过得很轻松!嵌入式系统仍然存在问题 -
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-10-10
      • 1970-01-01
      • 2016-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-05
      相关资源
      最近更新 更多