This is a simple question, but I would just like to throw this out there and appreciate if anyone could validate if my understanding is correct or provide some more insight. My apologies in advance if this is a duplicate post.
Eg. In the code below:
(1) stack_overflow.c
int main() {
while (1) {
int some_int = 0;
char* some_pointer = some_function();
// ... some other code ....
}
}
(2) no_overflow.c
int main() {
int some_int;
char* some_pointer;
while (1) {
some_int = 0;
some_pointer = some_function();
// ... some other code ....
}
}
Am I correct in saying that in the 1st code snippet, this code would eventually cause a stack overflow because of the variables continually being declared inside of the infinite loop? (The infinite loop is intentional)
Whereas, in the second code snippet we would actually be reusing the same parts of memory, which is the desired outcome as it would be more efficient.
Would compiler optimisation be able to detect this and prevent the stack overflow, if so which c compilers & optimisation levels would achieve this?
CodePudding user response:
This is not the case.
Each time the body of the loop is entered, two variables are created on the stack. Those variables are then destroyed when the loop hits the ending }
. After the loop condition is tested and the body is reentered, a new pair of variables are created.
CodePudding user response:
Am I correct in saying that in the 1st code snippet, this code would eventually cause a stack overflow because of the variables continually being declared inside of the infinite loop?
No:
6.2.4 Storage durations of objectsC 2011 Online Draft
...
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.
35) Leaving the innermost block containing the declaration, or jumping to a point in that block or an embedded block prior to the declaration, leaves the scope of the declaration.
Each time through the loop new instances of some_int
and some_pointer
will be created at the beginning of the loop body and destroyed at the end of it - logically speaking, anyway. On most implementations I've used, storage for those items will be allocated once at function entry and released at function exit. However, that's an implementation detail, and while it's common you shouldn't rely on it being true everywhere.
If some_function
dynamically allocates memory or some other resource that doesn't get freed before the end of the loop you could exhaust your dynamic memory pool or whatever, but it shouldn't cause a stack overflow as such.
CodePudding user response:
normally no but it's not the best practice.
however, if some_function()
is allocating a variable with every call, and it's not being freed in the same loop, you will lose the location of your allocated variable and have memory errors.
please share the rest of the code for a clearer answer.