什么时候会重新分配堆栈内存?
When will stack memory be reallocated?
有如下代码:
int fun(){
char* pc = NULL;
{
char ac[100] = "addjfidsfsfds";
pc = ac;
}
...
pc[0] = 'd';
printf("%s\n", pc);
...
}
那么,在ac
的范围结束后,我可以安全地使用pc
吗?因为我不确定分配给 ac
的堆栈内存是否会被编译器重新分配用于其他用途。
在您的示例中,在内部范围之外使用 pc
是不安全的。因为 ac
在 pc = ac
之后立即被销毁,所以你有一个经典的悬挂指针。启用足够多的警告后,我假设大多数编译器都会发出警告。
这可能似乎可以在您的系统上运行,但这并不意味着它是安全的。一些编译器可能会选择一次回收所有基元作为优化,但他们不需要这样做。
来自 C 标准#6.2.1p4 [强调我的]
Every other identifier has scope determined by the placement of its declaration (in a declarator or type specifier). If the declarator or type specifier that declares the identifier appears outside of any block or list of parameters, the identifier has file scope, which terminates at the end of the translation unit. If the declarator or type specifier that declares the identifier appears inside a block or within the list of parameter declarations in a function definition, the identifier has block scope, which terminates at the end of the associated block. ......
变量ac
是一个本地(自动)non-static变量,它的生命周期仅限于它的范围,即声明它的块。任何在其生命周期之外访问它的尝试都会导致未定义的行为。
来自 C 标准#6.2.4p2 [强调我的]
The lifetime of an object is the portion of program execution during which storage is guaranteed to be reserved for it. An object exists, has a constant address,33) and retains its last-stored value throughout its lifetime.34) If an object is referred to outside of its lifetime, the behavior is undefined. The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.
您理解上的缺陷与对象的存储期限有关。除非您使用线程,否则您需要关注三种类型,静态、自动和分配。通过在块内声明 char ac[100] = "addjfidsfsfds";
并且没有 static
storage-class 说明符,存储持续时间为 automatic 并且其生命周期在块执行结束时结束.之后尝试访问该值是 未定义的行为。
C-Standard 在第 6.2.4 节中对此进行了详细说明,例如
C11 - 6.2.4 Storage durations of
objects
1 An object has a storage duration that determines its lifetime. There
are four storage durations: static, thread, automatic, and
allocated. Allocated storage is described in
7.22.3.
2 The lifetime of an object is the portion of program execution
during which storage is guaranteed to be reserved for it. An object
exists, has a constant address,33) and retains its last-stored value
throughout its lifetime.34) If an object is referred to outside of its
lifetime, the behavior is undefined. The value of a pointer
becomes indeterminate when the object it points to (or just past)
reaches the end of its lifetime.
3 An object whose identifier is declared without the storage-class
specifier _Thread_local, and either with external or internal linkage
or with the storage-class specifier static, has static storage
duration. Its lifetime is the entire execution of the program and its
stored value is initialized only once, prior to program startup.
( _Thread_local details omitted)
5 An object whose identifier is declared with no linkage and without
the storage-class specifier static has automatic storage duration, as
do some compound literals. The result of attempting to indirectly
access an object with automatic storage duration from a thread other
than the one with which the object is associated is
implementation-defined.
6 For such an object that does not have a variable length array
type, its lifetime extends from entry into the block with which it is
associated until execution of that block ends in any way. (Entering
an enclosed block or calling a function suspends, but does not end,
execution of the current block.) If the block is entered recursively,
a new instance of the object is created each time. The initial value
of the object is indeterminate. If an initialization is specified for
the object, it is performed each time the declaration or compound
literal is reached in the execution of the block; otherwise, the value
becomes indeterminate each time the declaration is reached.
7 For such an object that does have a variable length array type,
its lifetime extends from the declaration of the object until
execution of the program leaves the scope of the declaration.35) If
the scope is entered recursively, a new instance of the object is
created each time. The initial value of the object is indeterminate.
如果有关于是否允许访问值的问题,请查阅标准。
它可能在块结束后重新分配(当它超出范围时)。
是否将重新分配,取决于程序和运行所在机器的体系结构(以及编译器)。
当您声明另一个局部变量(在堆栈上)时,可能 被重新分配; and/or,当您进行函数调用时(将参数值和 return 地址压入堆栈,并让被调用函数声明新变量)。
理论上 可能 它可能会在 pseudo-random 时间通过硬件中断或类似方式重新分配。在某些实现中,中断服务处理程序(可能 运行 在任何时候)通过将当前机器状态保存在堆栈上来启动。
有如下代码:
int fun(){
char* pc = NULL;
{
char ac[100] = "addjfidsfsfds";
pc = ac;
}
...
pc[0] = 'd';
printf("%s\n", pc);
...
}
那么,在ac
的范围结束后,我可以安全地使用pc
吗?因为我不确定分配给 ac
的堆栈内存是否会被编译器重新分配用于其他用途。
在您的示例中,在内部范围之外使用 pc
是不安全的。因为 ac
在 pc = ac
之后立即被销毁,所以你有一个经典的悬挂指针。启用足够多的警告后,我假设大多数编译器都会发出警告。
这可能似乎可以在您的系统上运行,但这并不意味着它是安全的。一些编译器可能会选择一次回收所有基元作为优化,但他们不需要这样做。
来自 C 标准#6.2.1p4 [强调我的]
Every other identifier has scope determined by the placement of its declaration (in a declarator or type specifier). If the declarator or type specifier that declares the identifier appears outside of any block or list of parameters, the identifier has file scope, which terminates at the end of the translation unit. If the declarator or type specifier that declares the identifier appears inside a block or within the list of parameter declarations in a function definition, the identifier has block scope, which terminates at the end of the associated block. ......
变量ac
是一个本地(自动)non-static变量,它的生命周期仅限于它的范围,即声明它的块。任何在其生命周期之外访问它的尝试都会导致未定义的行为。
来自 C 标准#6.2.4p2 [强调我的]
The lifetime of an object is the portion of program execution during which storage is guaranteed to be reserved for it. An object exists, has a constant address,33) and retains its last-stored value throughout its lifetime.34) If an object is referred to outside of its lifetime, the behavior is undefined. The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.
您理解上的缺陷与对象的存储期限有关。除非您使用线程,否则您需要关注三种类型,静态、自动和分配。通过在块内声明 char ac[100] = "addjfidsfsfds";
并且没有 static
storage-class 说明符,存储持续时间为 automatic 并且其生命周期在块执行结束时结束.之后尝试访问该值是 未定义的行为。
C-Standard 在第 6.2.4 节中对此进行了详细说明,例如
C11 - 6.2.4 Storage durations of objects
1 An object has a storage duration that determines its lifetime. There are four storage durations: static, thread, automatic, and allocated. Allocated storage is described in 7.22.3.
2 The lifetime of an object is the portion of program execution during which storage is guaranteed to be reserved for it. An object exists, has a constant address,33) and retains its last-stored value throughout its lifetime.34) If an object is referred to outside of its lifetime, the behavior is undefined. The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.
3 An object whose identifier is declared without the storage-class specifier _Thread_local, and either with external or internal linkage or with the storage-class specifier static, has static storage duration. Its lifetime is the entire execution of the program and its stored value is initialized only once, prior to program startup.
( _Thread_local details omitted)
5 An object whose identifier is declared with no linkage and without the storage-class specifier static has automatic storage duration, as do some compound literals. The result of attempting to indirectly access an object with automatic storage duration from a thread other than the one with which the object is associated is implementation-defined.
6 For such an object that does not have a variable length array type, its lifetime extends from entry into the block with which it is associated until execution of that block ends in any way. (Entering an enclosed block or calling a function suspends, but does not end, execution of the current block.) If the block is entered recursively, a new instance of the object is created each time. The initial value of the object is indeterminate. If an initialization is specified for the object, it is performed each time the declaration or compound literal is reached in the execution of the block; otherwise, the value becomes indeterminate each time the declaration is reached.
7 For such an object that does have a variable length array type, its lifetime extends from the declaration of the object until execution of the program leaves the scope of the declaration.35) If the scope is entered recursively, a new instance of the object is created each time. The initial value of the object is indeterminate.
如果有关于是否允许访问值的问题,请查阅标准。
它可能在块结束后重新分配(当它超出范围时)。
是否将重新分配,取决于程序和运行所在机器的体系结构(以及编译器)。
当您声明另一个局部变量(在堆栈上)时,可能 被重新分配; and/or,当您进行函数调用时(将参数值和 return 地址压入堆栈,并让被调用函数声明新变量)。
理论上 可能 它可能会在 pseudo-random 时间通过硬件中断或类似方式重新分配。在某些实现中,中断服务处理程序(可能 运行 在任何时候)通过将当前机器状态保存在堆栈上来启动。