使用卷曲支架从堆栈中删除分配
Use curly braces to remove allocations from the stack
假设我在一种方法中有很多堆栈分配。
如果我将卷曲括号添加到一组代码中,则分配的对象会在范围内弹出堆栈,还是在发布内存之前需要退出该方法?
我还应该补充说,这是在MFC应用程序中完成的。
void LongMethod()
{
{
struct someLargeStruct;
// Do a lot of work and allocations.
}
{
struct anotherLargeStruct;
// more work here.
}
}
只是为了进一步澄清 - 是的,标准需要在块范围末尾释放自动存储,请参见[basic.stc.auto]/1:
块范围变量明确声明为
register
或未明确声明为static
或extern
具有自动存储持续时间。这些实体的存储将持续到创建其创建的块出口为止。
但是,需要编译器仅实现程序的可观察行为( as-if 规则):
...需要实现(仅)(仅)抽象机的可观察行为...
由于该标准将自动存储视为无限的,并且没有其他方法可以观察堆栈使用情况,因此,在AS-IF规则下,符合编译器的编译器并不是在每个范围结束时都严格释放内存。p>的确,我们观察到GCC,Clang和MSVC更喜欢在功能启动时分配堆栈空间,并在功能退出处进行处理。尽管至少它们似乎在不同的块范围之间重复使用内存:
int do_something_with(int*);
int do_something_with(long long*);
void do_something()
{
{
int x[100];
do_something_with(x);
}
{
long long y[100];
do_something_with(y);
}
}
分配的堆栈框架:800字节(x
和y
共享相同的空间):
do_something():
sub rsp, 808
mov rdi, rsp
call do_something_with(int*)
mov rdi, rsp
call do_something_with(long long*)
add rsp, 808
ret
没有块范围的行为略有变化,我们不再观察内存重复使用:
int do_something_with(int*);
int do_something_with(long long*);
void do_something()
{
int x[100];
do_something_with(x);
long long y[100];
do_something_with(y);
}
分配的堆栈框架:1200字节(x
y
):
do_something():
sub rsp, 1208
mov rdi, rsp
call do_something_with(int*)
lea rdi, [rsp+400]
call do_something_with(long long*)
add rsp, 1208
ret
是的,是的,块scopes有一些效果,但不要指望它与这些范围完全一致。
它可能在递归功能中特别令人烦恼(示例):
int do_something_with(long long*);
int bar();
void foo()
{
{
if (bar())
foo(); // don't count on this being efficient
}
{
long long y[10000];
do_something_with(y);
}
}
因此,将重型堆栈用户分为单独的功能要安全得多。
c 中没有 stack (至少不是您想到的方式,有std::stack
容器适配器,但完全不同)。
但是,有一个自动存储,通常在堆栈上实现,但不能(例如,它可以在寄存器中)。
但是,对于自动存储,
对象的存储在开始时分配 封闭代码块并在末尾进行划分。所有本地对象 有此存储持续时间,除了那些被宣布为静态,外部或 thread_local。
(https://en.cppreference.com/w/cpp/language/storage_duration)
这意味着,如果编译器决定使用堆栈存储变量,则应知道其存储在封闭块的末尾结束。而且,尽管编译器目前没有义务减少堆栈指针,但这将是实施问题的严重质量。
- 双链表堆栈删除函数不起作用
- C++对自动(堆栈)指针使用运算符删除
- 使用链表在堆栈中插入和删除
- 如何从堆栈末端删除0
- 删除堆栈上声明的对象
- 使用卷曲支架从堆栈中删除分配
- 运行时检查失败#2 - 变量周围的堆栈'myArray'已损坏.- 似乎无法弄清楚如何删除此错误
- 指向堆栈对象的指针是否在超出范围时被删除
- C++不允许堆栈实例,但允许新的删除
- C++为什么创建一个新节点来删除堆栈上的节点是错误的
- 即使指针在函数堆栈中,我也必须删除它吗
- 从分配在堆栈上的对象指针的向量中删除元素
- Qt - 堆栈上具有父级的 QObject 如何被删除两次?
- C :删除在堆栈上声明的结构的字段
- 使用删除后指针是否指向堆栈或堆
- 我可以使用C++删除堆栈中的特定位置数据吗?
- 删除时,QObject是否区分堆栈和堆分配的子级
- 堆栈是如何组织的?:删除二叉树
- 删除具有堆栈指针的派生类
- C++堆栈;删除顶部值并放入变量中