问题标签 [stack-allocation]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
3 回答
24767 浏览

c++ - 变长 std::array 像

由于我通常使用的 C++ 编译器允许可变长度数组(例如,取决于运行时大小的数组),我想知道是否有类似std::array可变大小的东西?当然std::vector是可变大小的,但它在堆上分配,并在需要时重新分配。

我喜欢在运行时定义大小的堆栈分配数组。是否有任何std可能具有此功能的模板?也许使用std::vector固定的最大尺寸?

0 投票
7 回答
1573 浏览

c++ - 如何实现仅在堆栈上分配的字符串

在大约十年前的一个项目中,我们发现std::vector动态分配会导致严重的性能消耗。在这种情况下,分配了许多小向量,因此快速的解决方案是编写一个类似向量的类,该类包装一个基于堆栈的预分配char数组,用作其容量的原始存储。结果是一个static_vector<typename T, std::size_t Max>. 如果你知道一些基础知识,这样的东西很容易写,而且你可以在网上找到不少这样的野兽。事实上,boost现在也有一个。

现在在嵌入式平台上工作,我们碰巧需要一个static_basic_string. 那将是一个字符串,它在堆栈上预先分配固定的最大内存量并将其用作其容量。

起初我认为这应该相当容易(static_vector毕竟它可以基于现有std::basic_string的 . 它比std::vector's 接口复杂得多。尤其是实现附带的find()功能系列std::basic_string不仅仅是一项乏味的任务。

这让我再次思考。毕竟,这是创建分配器的目的:根据其他方式new替换分配。delete然而,说分配器接口笨拙是轻描淡写的。有几篇文章对此进行了解释,但我在过去 15 年中看到如此之的本土分配器是有原因的。

所以这是我的问题:

如果你必须实现一个basic_string相似的,你会怎么做?

  • 自己写static_basic_string
  • 写一个分配器传递给std::basic_string?
  • 做一些我没有想到的事情?
  • 使用我不知道的 boost 中的东西?

与往常一样,对我们来说有一个相当重要的限制:在嵌入式平台上,我们绑定到 GCC 4.1.2,所以我们只能使用 C++03、TR1 和 boost 1.52。

0 投票
3 回答
153 浏览

c++ - g ++编译器提示在堆栈上分配

是否有任何方法可以向编译器提示某些对象可能具有更静态的行为,并在堆栈而不是堆上分配东西?例如,字符串对象可能在某些函数中具有某种恒定大小。我问这个是因为我试图通过使用 OpenMP 来提高应用程序的性能。我已经将串行部分从 50 秒提高到了 20 秒,并行性提高到了 12 秒(提到大部分代码可以并行运行)。我正在努力继续改进。我认为一个限制与同一进程内动态内存的连续分配和释放有关。到目前为止,串行优化与合并到更 ANSI C 的方法有关,变量分配更硬编码(它们是动态分配的,但考虑到最坏的情况,所以一切都分配一次)。现在我几乎被卡住了,因为我已经到达了有很多 C++ 方法的代码的一部分。

0 投票
3 回答
226 浏览

c++ - 编译器如何管理运行时堆栈?

这个网站上有很多关于堆栈和堆的问题。但我想知道编译器实际上是如何管理堆栈的?基于堆栈的分配是在运行时还是编译时决定的?考虑以下示例:

这里的问题是何时分配对象 t?内存将在编译时或运行时分配?我知道局部变量,对象在函数被调用时被分配并在函数终止时被销毁。

0 投票
0 回答
342 浏览

arrays - 堆栈分配的不可变数组

我在 f# 中对uint64;的短数组进行了广泛的计算。我想堆栈分配它们以避免垃圾收集器运行。在 C++ 中,我会这样做:

但是 f# 似乎没有原始的堆栈分配数组类型?

0 投票
3 回答
2565 浏览

c++ - C++ 替代 C99 VLA(目标:保持性能)

我正在将一些大量使用可变长度数组 (VLA) 的 C99 代码移植到 C++。

我用在堆上分配内存的数组类替换了 VLA(堆栈分配)。性能损失巨大,下降了 3.2 倍(参见下面的基准)。 我可以在 C++ 中使用什么快速 VLA 替换?我的目标是在为 C++ 重写代码时最大程度地减少性能损失。

向我建议的一个想法是编写一个数组类,该类在该类中包含一个固定大小的存储(即可以堆栈分配)并将其用于小型数组,并自动切换到较大数组的堆分配。我的实现在帖子的末尾。它工作得相当好,但我仍然无法达到原始 C99 代码的性能。为了接近它,我必须将这个固定大小的存储(MSL下面)增加到我不喜欢的大小。即使对于许多不需要它的小数组,我也不想在堆栈上分配太大的数组,因为我担心它会触发堆栈溢出。C99 VLA 实际上不太容易出现这种情况,因为它永远不会使用比需要更多的存储空间。

我遇到了std::dynarray,但我的理解是它没有被标准接受(还没有?)。

我知道 clang 和 gcc 支持 C++ 中的 VLA,但我也需要它与 MSVC 一起使用。事实上,更好的可移植性是重写为 C++ 的主要目标之一(另一个目标是将原本是命令行工具的程序变成可重用的库)。


基准

MSL指的是我切换到堆分配的数组大小。我对一维和二维数组使用不同的值。

原始 C99 代码:115 秒。
MSL = 0(即堆分配):367 秒(3.2x)。
1D-MSL = 50,2D-MSL = 1000:187 秒 (1.63x)。
1D-MSL = 200,2D-MSL = 4000:143 秒 (1.24x)。
1D-MSL = 1000,2D-MSL = 20000:131 (1.14x)。

进一步增加MSL会进一步提高性能,但最终程序将开始返回错误的结果(我假设是由于堆栈溢出)。

这些基准测试是在 OS X 上使用 clang 3.7,但 gcc 5 显示了非常相似的结果。


代码

这是我当前使用的“smallvector”实现。我需要一维和二维向量。我切换到 size 以上的堆分配MSL

0 投票
1 回答
3361 浏览

java - Hotspot 什么时候可以在栈上分配对象?

从 Java 6 左右开始,Hotspot JVM 可以进行转义分析并在堆栈上分配非转义对象,而不是在垃圾收集堆上。这会加速生成的代码并减少垃圾收集器的压力。

Hotspot何时能够堆叠分配对象的规则是什么?换句话说,我什么时候可以依靠它来进行堆栈分配?

编辑:这个问题是重复的,但是(IMO)下面的答案比原始问题的答案更好。

0 投票
1 回答
541 浏览

common-lisp - 显式堆栈分配的数据

我认为在 Common Lisp 的大多数实现中,cons 单元通常/总是堆分配(请参阅Why is consing in Lisp slow?

Common Lisp 确实提供了一种从函数返回多个值的工具(values在返回时和multiple-value-bind在调用点使用)。我在这里推测了一下,但我认为这种构造的动机有两个方面:1)truncate在您不关心丢弃值的典型情况下使函数更易于使用;2)使其成为可能返回多个值,根本不使用堆分配的数据结构,并且(取决于实现(?))完全避免堆(以及以后的 GC 开销)。

Common Lisp(或可能像 SBCL 这样的特定实现)是否让您能够使用堆栈分配的数据(可能与弱引用之类的东西结合使用)或创建复合/大型值类型(类似于 C 中的结构)?

0 投票
1 回答
301 浏览

c++ - 如何在 C++ 中模拟堆栈帧?

我正在编写一个容器,它alloca在内部使用来在堆栈上分配数据。使用aside的风险alloca,假设我必须将它用于我所在的域(它部分是一个学习练习alloca,部分是为了研究动态大小的堆栈分配容器的可能实现)。

根据(强调我的)man页面:alloca

alloca() 函数在调用者的堆栈帧中分配 size 个字节的空间。 当调用 alloca() 的函数返回给它的调用者时,这个临时空间会自动释放。

使用特定于实现的功能,我设法以调用者堆栈用于此函数级“范围”的方式强制内联。

但是,这意味着以下代码将在堆栈上分配大量内存(编译器优化除外):

在不知道这个容器的实现细节的情况下,人们可能会期望它分配的任何内存在instance超出范围时都会被释放。情况并非如此,并且可能在封闭函数的持续时间内导致堆栈溢出/高内存使用。

想到的一种方法是显式释放析构函数中的内存。除了对生成的程序集进行逆向工程外,我还没有找到这样做的方法(另请参见this)。

我想到的唯一其他方法是在编译时指定最大大小,使用它来分配固定大小的缓冲区,在运行时指定实际大小并在内部使用固定大小的缓冲区。这样做的问题是它可能非常浪费(假设每个容器的最大值为 256 个字节,但大多数时候只需要 32 个字节)。

因此这个问题;我想找到一种方法来为这个容器的用户提供这些范围语义。不可移植很好,只要它在其目标平台上可靠(例如,一些仅适用于 x86_64 的文档化编译器扩展很好)。

我很欣赏这可能是一个XY 问题,所以让我清楚地重申我的目标:

  • 我正在编写一个必须始终在堆栈上分配其内存的容器(据我所知,这排除了 C VLA)。
  • 容器的大小在编译时是未知的。
  • 我想保持记忆的语义,就好像它被一个std::unique_ptr容器内部保存一样。
  • 虽然容器必须具有 C++ API,但使用 C 的编译器扩展是可以的。
  • 该代码现在只需要在 x86_64 上工作。
  • 目标操作系统可以是基于 Linux 或 Windows 的,它不需要同时在两者上工作。
0 投票
0 回答
458 浏览

static-allocation - 编译器设计中的静态分配和堆栈分配

我不清楚是静态和堆栈分配是什么?静态分配是静态的,堆栈分配是动态的吗?那么堆分配属于哪里呢?

激活记录与此有何关系?我认为激活记录是一个类似于激活树的概念性东西,并没有任何物理存在。

以下目标机器码是什么意思?

静态分配:

堆栈分配: