我正在编写一个容器,它alloca
在内部使用来在堆栈上分配数据。使用aside的风险alloca
,假设我必须将它用于我所在的域(它部分是一个学习练习alloca
,部分是为了研究动态大小的堆栈分配容器的可能实现)。
根据(强调我的)man
页面:alloca
alloca() 函数在调用者的堆栈帧中分配 size 个字节的空间。 当调用 alloca() 的函数返回给它的调用者时,这个临时空间会自动释放。
使用特定于实现的功能,我设法以调用者堆栈用于此函数级“范围”的方式强制内联。
但是,这意味着以下代码将在堆栈上分配大量内存(编译器优化除外):
for(auto iteration : range(0, 10000)) {
// the ctor parameter is the number of
// instances of T to allocate on the stack,
// it's not normally known at compile-time
my_container<T> instance(32);
}
在不知道这个容器的实现细节的情况下,人们可能会期望它分配的任何内存在instance
超出范围时都会被释放。情况并非如此,并且可能在封闭函数的持续时间内导致堆栈溢出/高内存使用。
想到的一种方法是显式释放析构函数中的内存。除了对生成的程序集进行逆向工程外,我还没有找到这样做的方法(另请参见this)。
我想到的唯一其他方法是在编译时指定最大大小,使用它来分配固定大小的缓冲区,在运行时指定实际大小并在内部使用固定大小的缓冲区。这样做的问题是它可能非常浪费(假设每个容器的最大值为 256 个字节,但大多数时候只需要 32 个字节)。
因此这个问题;我想找到一种方法来为这个容器的用户提供这些范围语义。不可移植很好,只要它在其目标平台上可靠(例如,一些仅适用于 x86_64 的文档化编译器扩展很好)。
我很欣赏这可能是一个XY 问题,所以让我清楚地重申我的目标:
- 我正在编写一个必须始终在堆栈上分配其内存的容器(据我所知,这排除了 C VLA)。
- 容器的大小在编译时是未知的。
- 我想保持记忆的语义,就好像它被一个
std::unique_ptr
容器内部保存一样。 - 虽然容器必须具有 C++ API,但使用 C 的编译器扩展是可以的。
- 该代码现在只需要在 x86_64 上工作。
- 目标操作系统可以是基于 Linux 或 Windows 的,它不需要同时在两者上工作。