在C/C++中,完成一个作用域块后堆栈上的内存是否被释放并且可以重用吗?
例如,假设进入函数后堆栈上有 100 个空闲字节。
void function(void)
{
{
uint8_t buffer1[80];
// Do something with the buffer
}
{
uint8_t buffer2[80];
// Do Something with the buffer
}
}
是否可以为 buffer2 分配足够的内存,还是仅在函数结束时释放用于 buffer1 的内存?
发生的情况取决于编译器......
either_buffer[80];
)sp
)会递减。缓冲器被作用。堆栈指针递增。(1)在函数栈帧中分离缓冲区(伪代码):
typedef unsigned char uint8_t;
void do_something(uint8_t *);
uint8_t *sp;
void
function(void)
{
uint8_t buffer1[80];
uint8_t buffer2[80];
{
// Do something with the buffer
do_something(buffer1);
}
{
// Do Something with the buffer
do_something(buffer2);
}
}
(2)函数栈帧中的单个区域(伪代码):
typedef unsigned char uint8_t;
void do_something(uint8_t *);
uint8_t *sp;
void
function(void)
{
uint8_t either_buffer[80];
{
uint8_t *buffer1 = either_buffer;
// Do something with the buffer
do_something(buffer1);
}
{
uint8_t *buffer2 = either_buffer;
// Do Something with the buffer
do_something(buffer2);
}
}
(3)堆栈指针根据需要递增/递减(伪代码):
typedef unsigned char uint8_t;
void do_something(uint8_t *);
uint8_t *sp;
void
function(void)
{
{
uint8_t *buffer1 = sp -= 80;
// Do something with the buffer
do_something(buffer1);
sp += 80;
}
{
uint8_t *buffer2 = sp -= 80;
// Do Something with the buffer
do_something(buffer2);
sp += 80;
}
}
实际发生的情况(对于 x86):
typedef unsigned char uint8_t;
void do_something(uint8_t *);
uint8_t *sp;
void
function(void)
{
{
uint8_t buffer1[80];
// Do something with the buffer
do_something(buffer1);
}
{
uint8_t buffer2[80];
// Do Something with the buffer
do_something(buffer2);
}
}
这是汇编代码:
.file "orig.c"
.text
.comm sp,8,8
.globl function
.type function, @function
function:
.LFB0:
.cfi_startproc
pushq %rbp #
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp #,
.cfi_def_cfa_register 6
subq $80, %rsp #,
# orig.c:14: do_something(buffer1);
leaq -80(%rbp), %rax #, tmp87
movq %rax, %rdi # tmp87,
call do_something #
# orig.c:20: do_something(buffer2);
leaq -80(%rbp), %rax #, tmp88
movq %rax, %rdi # tmp88,
call do_something #
# orig.c:22: }
nop
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size function, .-function
.ident "GCC: (GNU) 8.3.1 20190223 (Red Hat 8.3.1-2)"
.section .note.GNU-stack,"",@progbits
这相当于以下伪代码:
typedef unsigned char uint8_t;
void do_something(uint8_t *);
uint8_t *sp;
void
function(void)
{
{
uint8_t *buffer1 = sp - 80;
// Do something with the buffer
do_something(buffer1);
}
{
uint8_t *buffer2 = sp - 80;
// Do Something with the buffer
do_something(buffer2);
}
}