假设我们有以下代码:
void foo() {
char buffer[100];
}
在C中有一种(最好是便携式(方式来换取 buffer 从运行时堆栈(类似((返回?
no。您可以在C中做的最好的方法是使用范围:
void foo()
{
{
char buffer[100];
}
}
并依靠编译器来考虑内部范围退出后再次使用buffer
的100个字节。不幸的是,标准不能保证这一点,您需要依靠编译器。例如,在典型的Linux机器上考虑以下程序,其堆栈空间为8192KB(ulimit -s
(:
#include <stdio.h>
int main(void)
{
{
char buffer1[8192 * 800] = { 0 };
((char volatile *)buffer1)[0] = buffer1[0];
printf("%pn", buffer1);
}
{
char buffer2[8192 * 800] = { 0 };
((char volatile *)buffer2)[0] = buffer2[0];
printf("%pn", buffer2);
}
return 0;
}
(怪异的铸件是防止缓冲变量被优化。(
当不使用优化构建时,该程序将溢出某些编译器上的可用堆栈空间。例如,clang -O0
将崩溃,但是clang -O1
将重复使用buffer2
的buffer1
内存,并且两个地址都相同。换句话说,当示波器退出时,buffer1
已被"释放"。
gcc也将在-O0
处进行此优化。
给定:
void foo(void) {
char buffer[100];
}
对象buffer
的 lifetime 在执行到达开放 {
(输入函数时(并在执行离开块时结束,到达闭合}
(或以其他方式,例如以其他方式(goto
,break
或return
语句(。
除离开块外,没有办法结束buffer
的寿命。如果您想对其进行处理,则必须以其他方式分配它。例如,如果您通过调用malloc()
分配对象,则可以(几乎必须(通过调用free
:
void foo(void) {
char *buffer_ptr = malloc(100);
if (buffer_ptr == NULL) /* error handling code here */
/* ... */
if (we_no_longer_need_the_buffer) {
free(buffer_ptr);
}
/* now buffer_ptr is a dangling pointer */
}
一种替代方法是通过在嵌套块中定义buffer
的寿命:
void foo(void) {
/* ... */
{
char buffer[100];
/* ... */
}
/* buffer's lifetime has ended */
}
,但仅仅是因为buffer
的寿命在控制离开内部块时结束,这并不能保证它在物理上被划分。在抽象计算机中,buffer
离开内部块后不再存在,但是生成的代码可能仅仅因为它更方便而将其留在堆栈上。
如果要控制分配和交易,则需要使用malloc
和free
。
因为 char buffer[100];
被声明为 void foo()
的函数堆栈本地,当 void foo()
返回时, buffer
的存储空间被发布以进行重复使用,并且在此之后不再有效。
因此,您无需执行或可以做任何事情来" DealLocate buffer ",因为buffer
自动处理的是具有自动存储时间例如请参阅:C11标准-6.2.4对象的存储持续时间(P5(
它是自动变量,您不必做任何事情,因为离开范围时它将重新分配。在您的情况下,当您从功能返回
时如果要使范围缩小范围,只需将其放置在另一个范围内即可。
foo()
{
for(... .)
{
// if defined here it will be only in the for loop scope
}
{
// if defined here it will be only in this internal scope
}
}
裸露的是它需要允许它的C标准。