【问题标题】:C++ Should I allocate large structs on the heap or the stack?C++ 我应该在堆还是栈上分配大型结构?
【发布时间】:2021-07-09 07:37:48
【问题描述】:

我应该考虑使用new 关键字(或任何其他动态分配方法)在堆/空闲存储上分配什么结构大小,而不是在堆栈上分配?

10 字节? 20字节? 200 字节? 2KB? 2MB?从来没有?

即使我想通过指针传递它,我仍然可以从堆栈变量中获取引用。我知道堆栈变量会在范围结束时消失,而动态分配的变量不会。无论哪种方式我都可以处理,但到目前为止,我还没有找到任何关于 when 动态分配的指导。当然,不要在堆栈上放太多东西来避免堆栈溢出……但是有多少是太多了?

任何指导将不胜感激。

【问题讨论】:

  • IMO 你应该尽可能避免new(和new[])。如果你真的需要一个指针,那么使用像std::unique_ptrstd::shared_ptr 这样的智能指针(取决于所需的所有权语义),或者如果你需要一个“动态数组”(即改为使用std::vectornew[])。
  • 堆栈大小有限。您可能无法在堆栈上分配 2MB。
  • 多少算太多? .. 这大概取决于您的软件运行的系统。对于新的(ish)PC,运行 64 位操作系统(如 Windows 10 或 macOS),然后使用(比如说)16k 的堆栈就可以了;但是对于嵌入式 8 位微处理器,这会导致问题。在这些极端之间有很多“光谱”。
  • 堆栈大小取决于您的平台。有些默认为 8MB,有些为 1MB,有些为 64KB。我什至研究过一个堆栈大小为 256 字节的堆栈。
  • 作为指南,MSVC 静态分析器(用于 64 位构建)对使用超过 16k 堆栈空间的函数(默认情况下)发出警告 - 设置为 /analyze:stacksize '16384'

标签: c++ stack


【解决方案1】:

真正回答这个问题,你需要知道:

  • 堆栈有多大。这通常可以在编译时进行配置,但可能会受到目标平台的限制。

  • 堆栈上已经有什么了。这些知识可以通过使用确定性调用图或通过根据堆栈指针的当前值主动做出决策来获得。

如果没有上述所有条件,任何被动决定都将是一场赌博。这也意味着默认情况下这是一场赌博——事实上,在大多数情况下,我们必须相信编译器开发人员了解“典型”程序需要多少堆栈空间,并且我们对“典型”程序的看法确实一致并且经常。

从长远来看,就像任何优化问题一样,将赌注放在衡量整体性能和测试可能导致堆栈溢出的边缘情况上。

【讨论】:

  • 你已经回答了这个问题,就好像我有一个需要尝试解决的特定问题......我问的问题是每个人都应该问的问题,不?当然,这取决于堆栈的大小以及堆栈上的内容,这是不言而喻的。
  • @Alasdair 您已要求指导,我可以提供指导。如果你想要特定的阈值,你必须提供特定的上下文(也就是你有一个你想要解决的问题):编译器、设置、平台、分析统计。否则,您的 cmets 会建议您的问题过于宽泛或基于观点。
【解决方案2】:

(注意。我可能应该在回答之前先搜索一下,但这个问题本质上是How much stack usage is too much? 的重复,不过,这是我对它的看法。)

如果您打算长时间保留一个大缓冲区,那么您应该在堆上分配它。

如果您在递归函数中,那么在堆栈上分配大缓冲区会很快导致问题。

就个人而言,我会在堆栈上保持低于 ~4KiB 的缓冲区,并在堆上分配更大的缓冲区,除非您对程序有一个很好的了解,更具体地说,您的函数被调用的方式和位置。

话虽如此,如果您不断创建和销毁缓冲区,请考虑将它们放入堆栈。

(如果您正在开发嵌入式系统,那么情况就完全不同了。)

【讨论】:

    猜你喜欢
    • 2015-07-26
    • 2019-10-25
    • 2019-09-16
    • 1970-01-01
    • 2012-03-31
    • 2021-10-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多