【问题标题】:When is heap memory prefered over stack memory什么时候堆内存优先于堆栈内存
【发布时间】:2018-08-08 08:20:24
【问题描述】:

我知道本地数组是在堆栈上创建的,并且具有自动存储持续时间,因为当它们所在的函数结束时它们会被销毁。它们必须具有固定的大小:

{
   int foo[16];
}

使用运算符new[] 创建的数组具有动态存储持续时间并存储在堆上。它们可以有不同的尺寸。

{
    const int size = 16;
    int* foo = new int[size];
    // do something with foo
    delete[] foo;
}

堆栈的大小是固定的,并且对于每个进程都是有限的。

我的问题是: 为了减少堆栈内存消耗,何时从堆栈内存切换到堆内存是否有经验法则?

例子:

  • double a[2] 完全合理;
  • double a[1000000000] 很可能会导致堆栈溢出,如果堆栈大小为 1mb

切换到动态分配的合理限制在哪里?

【问题讨论】:

  • 非常接近this question 和我的答案
  • 经验法则:如果它适合堆栈,则在堆栈上分配它们(局部变量),如果它太大而无法放入堆栈,则动态分配。
  • 首先我宁愿推荐std::array而不是普通数组,或者std::vector而不是你自己的动态分配。然后至于应该开始使用std::vector 而不是std::array 的“断点”,这实际上取决于用例。 “经验法则”是元素计数器“足够小”,但“足够小”到底有多小,通常不是可以建议的。
  • 对于堆栈分配的数组,您需要在编译时知道它的大小。在实践中,数据结构的大小通常要到 runtime 才能知道。 (小缓冲区优化如果您想更深入地研究问题,可能会引起您的兴趣。)

标签: c++ stack stack-overflow heap-memory


【解决方案1】:

有关堆分配的讨论,请参阅 this answer

切换到动态分配的合理限制在哪里?

在几种情况下,包括:

  • automatic variables 太大。根据经验,我建议避免超过几千字节的调用帧(以及超过一兆字节的call stack)。如果您确定您的函数不能递归使用,则该限制可能会增加。在许多小型嵌入式系统上,堆栈受到更多限制(例如,几千字节),因此您需要对每个调用帧进行更多限制(例如,只有一百字节)。顺便说一句,在某些系统上,您可以更多地增加调用堆栈限制(可能达到几 GB),但这也是系统管理员的问题。

  • 非 LIFO 分配规则,这种情况经常发生。

请注意,大多数 C++ 标准 containers 在堆中分配它们的数据,即使容器在堆栈上。例如,vector 类型的自动变量,例如本地std::vector<double> autovec; 已分配其数据堆(并在向量为destroyed 时释放)。阅读有关RAII 的更多信息。

【讨论】:

    猜你喜欢
    • 2011-08-15
    • 2019-12-07
    • 1970-01-01
    • 2018-09-27
    • 2017-02-08
    • 2012-06-03
    • 2011-10-21
    • 2011-06-13
    • 2011-05-28
    相关资源
    最近更新 更多