在C中取消分配局部定义的变量

D.F*_*kaz 1 c memory-management local-variables static-allocation stack-pointer

假设我们有以下代码:

void foo() {
  char buffer[100];
}
Run Code Online (Sandbox Code Playgroud)

在foo()返回之前,C语言中是否有一种(最好是可移植的)方式从运行时堆栈中释放缓冲区(又称添加esp,在程序集中为100

Nik*_* C. 5

不。您可以在C语言中做的最好的事情就是使用范围:

void foo()
{
    {
        char buffer[100];
    }
}
Run Code Online (Sandbox Code Playgroud)

并依靠编译器buffer在内部范围退出后再次考虑100字节的可用空间。不幸的是,这不是标准所保证的,您需要依赖编译器。例如,在具有8192KB(ulimit -s)堆栈空间的典型Linux计算机上考虑以下程序:

#include <stdio.h>

int main(void)
{
    {
        char buffer1[8192 * 800] = { 0 };
        ((char volatile *)buffer1)[0] = buffer1[0];
        printf("%p\n", buffer1);
    }

    {
        char buffer2[8192 * 800] = { 0 };
        ((char volatile *)buffer2)[0] = buffer2[0];
        printf("%p\n", buffer2);
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

(怪异的转换是为了防止缓冲区变量被优化掉。)

如果不进行优化构建,程序将在某些编译器上溢出可用的堆栈空间。clang -O0例如,将崩溃,但clang -O1将重复使用buffer1内存,buffer2并且两个地址将相同。换句话说,buffer1在范围退出时,某种意义上已被“释放”。

另一方面,即使在,GCC也会进行此优化-O0