这是一个简单的问题,但我只想把它扔出去,如果有人能验证我的理解是否正确或提供更多见解,我将不胜感激。如果这是重复的帖子,我提前道歉。
例如。在下面的代码中:
(1) stack_foverflow.c
int main() {
while (1) {
int some_int = 0;
char* some_pointer = some_function();
// ... some other code ....
}
}
(2) no_溢出.c
int main() {
int some_int;
char* some_pointer;
while (1) {
some_int = 0;
some_pointer = some_function();
// ... some other code ....
}
}
在第一个代码片段中,由于变量在无限循环中不断声明,这段代码最终会导致堆栈溢出,我说的对吗?(无限循环是有意的)
然而,在第二个代码片段中,我们实际上会重用内存的相同部分,这是所希望的结果,因为它会更高效。
编译器优化能够检测到这一点并防止堆栈溢出吗;优化级别是否可以实现这一点?
事实并非如此。
每次输入循环的主体时,都会在堆栈上创建两个变量。然后,当循环到达结束}
时,这些变量被销毁。在测试循环条件并重新输入主体之后,将创建一对新的变量。
我说的在第一个代码片段中,由于变量在无限循环中不断声明,这段代码最终会导致堆栈溢出,这是对的吗?
否:
6.2.4对象的存储持续时间C 2011在线草案
6对于这样一个没有可变长度数组类型的对象,它的生存期从进入与其关联的块开始延长,直到该块的执行以任何方式结束。(输入一个封闭的块或调用一个函数会暂停但不会结束当前块的执行。)如果该块是递归输入的,则每次都会创建一个新的对象实例。对象的初始值不确定如果为对象指定了初始化,则每次在执行块时达到声明或复合文字时都会执行该初始化;否则,每次到达声明时,该值都会变得不确定
7对于这样一个具有可变长度数组类型的对象,其生存期从对象的声明开始延长,直到程序的执行离开声明的范围35)如果递归地输入范围,则每次都会创建对象的新实例。对象的初始值不确定。
35)离开包含声明的最里面的块,或者跳到该块中的一个点或声明之前的嵌入块,就离开了声明的范围
每次通过循环,some_int
和some_pointer
的新实例都将在循环体的开始创建,并在循环体结束时销毁——无论如何,从逻辑上讲。在我使用过的大多数实现中,这些项的存储将在函数入口分配一次,并在函数出口释放。然而,这是一个实现细节,虽然它很常见,但你不应该依赖于它在任何地方都是真实的。
如果some_function
动态分配内存或其他在循环结束前没有释放的资源,则可能会耗尽动态内存池或其他资源,但不应导致堆栈溢出。
通常不会,但这不是最佳实践。但是,如果some_function()
在每次调用中都分配一个变量,并且它没有在同一个循环中释放,那么您将丢失已分配变量的位置,并出现内存错误。
请分享代码的其余部分以获得更清晰的答案。