在 C 中模拟 `alloca()`

Posted

技术标签:

【中文标题】在 C 中模拟 `alloca()`【英文标题】:emulating `alloca()` in C 【发布时间】:2016-12-02 14:36:12 【问题描述】:

如果您通读 GNU libs 文档,您会看到:

一些非 GNU 系统不支持 alloca,因此它的可移植性较差。 但是,用 C 编写的 alloca 的较慢仿真可用于 在有此缺陷的系统上使用。

假设 VLA 也不可用,alloca() 的 C 模拟会是什么样子?

【问题讨论】:

在 C++ 中这将相当容易,但我怀疑您是否可以在标准 C 中编写可移植的 alloca 函数。 真的吗?你能给出一个提示,你将如何在 C++ 中做到这一点? @user1095108 使用 C++ 你可以只使用 std::shared_ptr,我想。 @WillihamTotland 是的,如果你想从堆中分配。 一个 emulation 应该只尊重全局接口,我的意思是从当前函数返回时自动释放分配的块。本地对象的析构函数可以做到这一点,而像 shared_ptruniq_ptr 这样的智能指针会自动做到这一点。 【参考方案1】:

根据alloca()是什么

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

实现将是特定于平台的,并且可能编译器应该意识到这一点,因为生成的代码必须尊重堆栈帧处局部变量的非固定偏移量。因此,如果您的工具链没有 VLA - 您与它无关。

【讨论】:

【参考方案2】:

由于您正在查看GNU libc documentation,您可能会考虑如何在 GCC 中进行模拟。

GCC 提供了cleanup 属性,允许在变量超出范围时调用清理函数。

void foo (void *p) 
    printf("foo: %p\n", p);


int main(void) 
    int x __attribute__((cleanup(foo)));
    x = 7;
    printf("%p\n", &x);
    return 0;

在上面的程序中,当x超出范围时,foo()被传递给x的地址。

【讨论】:

这很有趣但不是很有用,因为 gcc 提供了 alloca 作为内置函数。 @n.m.不总是。我的意思是,GCC 并不总是为alloca 生成内联代码。这就是 GNU libc 提供模拟实现的原因。 <alloca.h> 头文件显示:#ifdef __GNUC__ #define alloca __builtin_alloca。它可能会也可能不会导致代码内联。 glibc 可以由 gcc 以外的编译器编译。 @n.m.如果不包含alloca.h,如果标志导致GCC 不内联alloca(),链接器将选择仿真。 alloca 需要在典型实现上操作堆栈指针。您不能只从链接器调用函数,所涉及的编译器必须提供一些支持(至少它不能重新排序堆栈上对象的分配等)。与自动变量相比,分配对象的生命周期也存在差异。

以上是关于在 C 中模拟 `alloca()`的主要内容,如果未能解决你的问题,请参考以下文章

在 C 中包装 alloca 函数

C中的alloca函数

C alloca 函数 - 当试图分配太多内存时会发生啥

alloca 函数范围内的 goto 是不是有效?

Alloca 实施

alloca 和 ObjectiveC 垃圾收集器