问题标签 [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 投票
5 回答
1936 浏览

c - alloca() 如何在内存级别上工作?

我试图弄清楚alloca()在内存级别上的实际工作方式。从linux 手册页

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

这是否意味着alloca()将按字节转发堆栈指针n?或者新创建的内存到底分配在哪里?

这与可变长度数组不完全相同吗?

我知道实现细节可能留给操作系统和其他东西。但我想知道一般来说这是如何完成的。

0 投票
1 回答
48 浏览

c++ - 在堆栈上分配任意常量大小的结构

我写了一个小型的工作插件服务器。插件是使用.so共享对象实现的,这些共享对象在运行时通过调用dlopen(header <dlfcn.h>) 在“服务器”中手动加载。

所有共享对象插件都具有相同的接口:

  • 基本上,do_something返回一个指向堆内存的指针,调用者应该释放它。
  • id只是一个唯一的标识符 per .so
  • T是每个特定的结构.so。其中一些共享相同的返回类型,而另一些则没有。这里的重点是,sizeof(T).so具体的。

服务器负责动态加载和读取.so二进制文件的符号。所有.so插件都可以通过do_something_proxy服务器二进制文件中定义的方法相互调用,该方法充当调用者和被调用者之间的粘合剂:

为了简化一点,假设这some_so_map是一个简单的std::unordered_map<size_t, so_handle_t>填充,使用一堆调用dlopen何时执行代理。

我的问题是每个调用者在编译时都do_something_proxy知道。T正如我之前所说,T可能因呼叫站点而异;但是对于任意呼叫站点T 永远不会改变。

作为参考,这是所有调用者使用的定义:

换句话说,do_something_proxy对于某些任意插件,id总是具有相同的返回类型。

如果不是为了代理,我可以只使用模板do_soemthing_proxy并传递T或使用std::array<int8_t, N>with ,并且当调用可以移动到堆栈时sizeof(T) == N,分配的不必要的内存不会被切片。但是,代理无法在编译期间知道所有可能的返回类型并导出无数版本的.Tdo_something_proxydo_something_proxy

所以我的问题是,有没有办法在其堆栈上do_soemthing_proxy分配有效大小T(即使用alloca或其他形式的堆栈分配)?

据我所知,alloca这里似乎不起作用,因为do_soemthing_proxy只能从do_something请求的插件的函数中接收一个值。do_soemthing_proxy将同时接收要分配的大小和要复制到分配的内存的字节。要是alloca能在两者之间“压扁”就好了……

std::array<int8_t, N>我知道我可以使用256 甚至 1024 的值在堆栈上分配固定数量的内存N。但是,这个解决方案有点脏。它不必要地将数据从一个堆栈帧复制到另一个堆栈帧,并限制了插件可以返回的数据量。最重要的是,(虽然我还没有对这个解决方案进行基准测试)除非编译器可以跨越动态边界删除副本,否则我假设复制 1024 字节比复制 iesizeof(std::string)字节更工作。

在一个理想的世界里,我相信do_soemthing_proxy应该返回一个用 RAII 处理这个的结构。一个const std::any堆栈分配的,如果你愿意的话。这甚至可能吗?

如果这在 c++ 中根本不可能,是否可以在汇编中以可移植的方式实现这种行为,即通过手动劫持堆栈或基指针?

谢谢。

0 投票
1 回答
30 浏览

c++11 - 堆栈分配类的成员在作用域结束时放置 new 会发生什么?

我有这个(编译)代码:

编译器是否处理了 A 和 B 中的向量?Afaik 要销毁像 A 和 B 这样分配的对象,我必须显式调用析构函数。我在这里不这样做,我想知道当作用域结束时是否仍然为 A 和 B 的成员向量调用析构函数。这当然是必要的,因为他们管理堆资源。