【问题标题】:Is it possible to allocate on stack是否可以在堆栈上分配
【发布时间】:2011-08-16 08:35:47
【问题描述】:

malloc 函数总是在堆上分配内存。但是,在研究Escape Analylis Article on Wikipedia 时,我了解到作为一种优化,编译器可以将堆分配转换为堆栈分配。例如,如果它发现分配的内存只被使用,然后在函数内部被释放。

现在我的问题是,有没有办法让程序员自己这样做。那就是在堆栈上分配内存?我知道 C99 允许将变量作为数组声明的大小给出,但说程序员想要调整它的大小。能做到吗?

【问题讨论】:

  • 为什么你想这样做?
  • C99 不要求您“一开始就分配”。您可以在代码中的任何位置“分配”VLA。但无法调整大小。
  • “不是一开始”是什么意思?调整大小有什么意义?

标签: c optimization compiler-construction


【解决方案1】:

alloca() 是您正在寻找的。当然,如果您静态知道结构尺寸,最好使用局部变量。

【讨论】:

  • 你打字比我快...无论如何,值得指出Why is alloca not considered good practice?(当然你的答案仍然正确)。
  • @eran,好吧,在转义分析的上下文中,我怀疑 OP 想在某种编译器后端使用它。在这种情况下,它应该足够安全使用。
  • Shiver : alloca 不是标准 C 语言,与 VLA 相比没有任何优势 - 应尽可能不鼓励使用它。
  • @paxdiablo,不幸的是,C99 也没有达到应有的标准——有很多平台可以使用alloca(),但没有 C99。因此,如果它是用于编译器后端,那么能够同时使用两者是合理的。
  • C99 is 应该是标准,它是 the 标准。我认为您的意思可能是“没有得到广泛支持”:-)
【解决方案2】:

C99 还允许您在函数内的任何位置分配可变长度数组 (VLA) 和其他变量,而不仅仅是在开始时,因此您关于能够在其他地方分配内存的观点没有实际意义。

你可以插入一个:

int arr[somevar];

函数中的任何位置并让它执行。

使用 VLA,您不再需要担心使用 malloc/free(或在某些实现中可用的臭名昭著的 alloca,这是进行基于堆栈的分配的另一种方式,a 代表 automatic)用于任意位置的可变大小分配。

如果您希望能够调整大小,您仍然必须使用标准内存分配函数,例如 mallocrealloc。 VLA 不提供这种级别的功能(目前)。

【讨论】:

    【解决方案3】:

    据我所知,将堆分配转换为堆栈分配是库的事情,而不是编译器可以控制的事情。实际上,在 Linux 上,malloc 使用brk 系统调用(调整堆栈大小)而不是使用mmap,但较大的页面除外。

    引用the source:

    The old goals we kept are
      1) try to get the long lived large allocations to use mmap()
      2) really large allocations should always use mmap()
      and we're adding now:
      3) transient allocations should use brk() to avoid forcing the kernel
         having to zero memory over and over again
    

    【讨论】:

    • 编译器在某些情况下可以做到这一点 - 例如,请参阅 MLkit 中的区域分析实现。由于非平凡的别名分析,使用 C 和类似语言会有点问题。
    • brk 将调整数据段的大小,而不是堆栈。
    猜你喜欢
    • 2014-06-10
    • 2019-09-22
    • 2014-10-11
    • 2020-09-02
    • 2010-09-17
    • 2020-03-30
    • 2014-10-03
    • 2021-10-01
    • 2017-06-21
    相关资源
    最近更新 更多