问题标签 [alloca]

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 投票
0 回答
90 浏览

llvm - 用于分配值的 LLVM def-use

我一直在探索 alloca 值的 def-use 。

我有以下 IR 代码 -

在运行 "%res" 的 def-use 链,并打印正在使用 "%res" 的指令。以下是输出 -

我发现在存储之前可以看到负载。有没有办法让 alloca 值的“使用”与它们出现在 IR 中的指令顺序完全相同?

0 投票
2 回答
152 浏览

c - 为什么我可以进入 alloca:d 变量的范围,而不是可变长度数组?

请参阅此测试程序:

它无法编译并出现错误“跳转到具有可变修改类型的标识符范围”(请参阅​​其他问题)。

但是,如果我将声明更改s为此(并包含alloca.h),它编译得很好:

为什么 C 标准允许跳转到使用 创建的对象的范围alloca,而不是可变长度数组?我以为他们是等价的。

0 投票
1 回答
196 浏览

c++ - 为什么这个 CMake 脚本找到“alloca”但仍然失败?

我在我的alloca一个项目中使用该功能,并决定使用 CMake 来确保它可用。所以我将这一点添加到我的 CMakeLists.txt 文件中:

当我运行 CMake 时,这是输出的(相关部分):

那么显示的代码如何找到函数但没有设置变量?或者是别的什么?

0 投票
2 回答
1193 浏览

c - 为什么`alloca`不检查它是否可以分配内存?

为什么不alloca检查它是否可以分配内存?

来自man 3 alloca

如果分配导致堆栈溢出,则程序行为未定义。… 如果堆栈帧无法扩展,则没有错误指示。

为什么alloca不/不能检查它是否可以分配更多内存?

我理解它alloca在堆栈上分配内存时在堆栈上分配内存的方式(s)brk。来自https://en.wikipedia.org/wiki/Data_segment#Heap

堆区由 malloc、calloc、realloc 和 free 管理,可以使用 brk 和 sbrk 系统调用来调整其大小

来自man 3 alloca

alloca() 函数在调用者的堆栈帧中分配 size 个字节的空间。

并且堆栈和堆正朝着收敛的方向增长,如下图所示:

在此处输入图像描述

(上图来自Dougct 在CC BY-SA 3.0下发布的Wikimedia Commons

现在两者都alloca返回(s)brk一个指向新分配内存开头的指针,这意味着它们都必须知道当前堆栈/堆在哪里结束。确实,来自man 2 sbrk

以 0 为增量调用 sbrk() 可用于查找程序中断的当前位置。

因此,按照我的理解,检查是否alloca可以分配所需的内存基本上归结为检查堆栈的当前端和堆的当前端之间是否有足够的空间。如果在堆栈上分配所需的内存会使堆栈到达堆,则分配失败;否则,它会成功。

那么,为什么不能使用这样的代码来检查是否alloca可以分配内存呢?

这对我来说更令人困惑,因为显然(s)brk可以进行此类检查。来自man 2 sbrk

brk() 将数据段的末尾设置为 addr 指定的值,当该值合理时,系统有足够的内存,并且进程不超过其最大数据大小(参见 setrlimit(2))。

所以如果(s)brk可以做这样的检查,那为什么不能alloca呢?

0 投票
4 回答
2113 浏览

c++ - 在堆栈上分配对齐的内存,如 _alloca

的文档在这里_alloca()说:

_alloca 例程返回一个指向已分配空间的 void 指针,该指针保证为存储任何类型的对象而适当对齐。

但是,这里说:

_alloca 需要 16 字节对齐,并且还需要使用帧指针。

因此,似乎在第一个参考文献中,他们忘记了大约 32 字节对齐的 AVX/AVX2 类型,例如__m256d.

让我感到困惑的另一件事是第一页说不_alloca()推荐使用,而它建议使用一个可以从堆而不是堆栈分配内存的函数(这在我的多线程应用程序中是不可接受的)。

那么有人可以指出我是否有一些现代的(也许是新的 C/C++ 标准?)对齐堆栈内存分配的方法?

说明1:请不要提供要求数组大小为编译时常量的解决方案。我的函数根据运行时参数值分配可变数量的数组项。

0 投票
1 回答
118 浏览

haskell - Using alloca- with c2hs

Consider from the c2hs documentation that this:

generates in Haskell

which binds the following C function:

Problem: Here I'm confused what the effect of alloca- has on the left side of, i.e., `Bool'.

Now I know that, in practice, what is happening is that alloca is somehow generating a Ptr Bool that peekBool can convert into an output argument. But what I'm terribly confused about is how alloca is doing this, given its type signature alloca :: Storable a => (Ptr a -> IO b) -> IO b. More specifically:

Question 1. When someone calls notebookQueryTabLabelPacking in Haskell, what does c2hs provide as argument for alloca's first parameter (Ptr a -> IO b)?

Question 2. In this case, what is the concrete type signature for alloca's first paramater (Ptr a -> IO b)? Is it (Ptr CBool -> IO CBool)?

0 投票
0 回答
93 浏览

c++ - 表达式局部变量

我试图提出(只是作为一个实验,没什么严重的)一个宏,它以更面向对象的方式包装alloca ,使用特殊的“构造函数”返回实例所需的大小以及指向函数的指针应该初始化它。

使用更多语句来编写很简单:

显然,如果它不是alloca,则将其包装在一个函数中会起作用,但这需要是内联的。

是否可以创建一个执行此类任务的表达式,并obj作为结果返回?设计不必保持不变,但通常应该有一个函数采用构造函数应该采用的参数并产生大小和初始化函数。如果alloca作为参数std::pair<size_t,void(*)(void *ptr)>,一切都会容易得多。

我怀疑它在 C++ 中可能无法实现,但只是出于好奇,它可以在 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 投票
2 回答
225 浏览

c - alloca() 和 setjmp 的作用是什么?

这个问题来自C 中 setjmp 和 longjmp 的实际用法以及我问的如何在 c 中的 for 循环中实现协程。

我正在研究 C. 的协程实现,并试图查看longjmp.

问题一:

使用后有什么魔力使堆栈routineB活着alloca(2048)?我听说alloca是邪恶的,但为什么它使堆栈看起来像扩展了。我应该这样使用它吗?

输出:

问题2:

删除后alloca(2048)。在告诉编译器禁用优化(-O2)后,它会给出不同的结果。

-O0

-O2

如果它不是未定义的,如何使代码获得相同的行为?如果是,请忘记 Q2。

0 投票
2 回答
915 浏览

gcc - 了解 GCC 的 alloca() 对齐和看似错过的优化

考虑以下通过alloca()函数在堆栈上分配内存的玩具示例:

使用 gcc 8.2 编译上述函数,-O3得到以下汇编代码:

老实说,我本来希望有更紧凑的汇编代码。


分配内存的 16 字节对齐

上面代码中的指令andq $-16, %rax导致在地址和(包括两者)之间rax包含(仅)16 字节对齐的地址。rsprsp + 15

这种对齐强制是我不明白的第一件事:为什么alloca()将分配的内存对齐到 16 字节边界?


可能错过优化?

无论如何,让我们考虑一下我们希望分配的内存alloca()是 16 字节对齐的。即便如此,在上面的汇编代码中,请记住call foo,如果我们注意堆栈内部的状态,GCC 在执行函数调用时假定堆栈与 16 字节边界对齐(即 )foo() 就在推送rbp寄存器之后:

我认为通过利用红色区域(即无需修改)和已经包含16 字节对齐地址rsp的事实,可以使用以下代码:rsp

寄存器中包含的地址rbp是 16 字节对齐的,因此rbp - 16也将对齐到 16 字节边界。

更好的是,新堆栈帧的创建可以被优化掉,因为rsp它没有被修改:

这只是错过的优化还是我在这里遗漏了其他东西?