是否随作用域分配和解除分配堆栈帧
Are stack frames allocated and deallocated with scope?
继上一个问题之后,我一直在查看VS2015代码分析的输出,并在函数中看到高堆栈使用率的警告,该警告可以简化如下;
class base
{
public:
virtual void Process();
Buffer[10000];
};
class derived1 : public base
{
public:
void Process();
}
class derived2 : public base
{
public:
void Process();
}
void MyFunc(int x)
{
switch(x)
{
case 0:
{
derived1 x;
x.Process();
} break;
case 1:
{
derived2 y;
y.Process();
} break;
}
}
分析警告我,我在MyFunc
中使用了 20,000 字节的堆栈。 情况是否如此,因为所有堆栈变量都在函数入口时分配并在函数出口时释放,而不是在它们使用作用域构造和破坏时? 只是好奇(但还不够好奇,无法在程序集输出;)中涉水( 这里的相关问题并不能完全给我正在寻找的答案。
堆栈帧分配由编译器自行决定。大多数编译器不会尝试使用大变量隔离本地作用域,但大多数编译器确实提供了像 alloca
或 C99 VLA 这样的工具,可以动态扩展现有堆栈帧。因此,架构问题不太可能发挥作用;这纯粹是实施细节的问题。
您可以将本地作用域括在 lambda 表达式中,以鼓励编译器提供此类隔离:
switch(x)
{
case 0:
[]{
derived1 x;
x.Process();
}(); break;
case 1:
[]{
derived2 y;
y.Process();
}(); break;
}
尽管如此,没有什么是可以保证的。
您可以使用 godbolt.org 联机编译器查看此类示例的机器代码反汇编。看起来这个技巧适用于 GCC,但在 Clang 上它仅适用于优化-O1
或更少,而在英特尔的编译器上它仅适用于 -O0
.
相关文章:
- 指针会被解除分配吗?
- 基于浅树的数据结构的内存分配器,用于频繁分配和解除分配
- 解除分配矩形 2D 数组会根据尺寸产生错误
- 为什么在正确解除分配内存时出现内存泄漏?
- 巨大的内存分配:堆栈与堆
- 堆栈变量超出范围时是否解除分配?
- 如何在不使用 "new" 关键字的情况下解除分配创建的对象的内存?
- 在 QStandardItemModel 中解除分配项目
- 有效地分配堆栈对象(由函数的值返回)到堆?
- 解除分配此特定 2D 阵列的内存
- C++删除数组只会解除分配第一项
- 为什么不能在 Visual C++ 中动态分配堆栈内存?但海湾合作委员会可以做到
- 为什么分配堆内存比分配堆栈记忆更快
- 在 c++ 中使用向量解除分配
- 与解除分配堆数组相关的语法混淆
- 解除分配与 C++ 中的结构关联的所有内存
- 安全分配堆栈分配的阵列
- 附加到具有非动态分配堆栈的向量
- 是否随作用域分配和解除分配堆栈帧
- 如果我使用 std::function 来捕获 lambda,我应该担心它被解除分配吗?