1

I was going through someone's code where I came across a thread:

while(TRUE)

{
 ......
 STRUCT_MSG_SYS_HEADER  sysHdr;
 .....
 ....
}

There are five threads like this, My point is that "STRUCT_MSG_SYS_HEADER sysHdr;" will lead to stackoverflow after some time or days... (Not tested though). So I decided to write a simple sample application

  1 #include "stdio.h"
  2
  3 struct infinite
  4 {
  5     int arr[1000000];
  6 }infinite;
  7
  8 int main()
  9 {
 10     while(1)
 11     {
 12         struct infinite infobj;
 13         printf("\ninfinite = %x\n", &infobj);
 14     }
 15     return 0;
 16 }

But here it is printing the same address for infobj. Is my thinking of stackoverflow is wrong or here compiler has done some optimization? (I consider myself good coder, but things like these force me to think again, read dennis richie again)

yhw42
  • 3,334
  • 2
  • 27
  • 24
Alam
  • 1,536
  • 15
  • 26
  • A good coder would never write void main :) main returns an int always. The compiler is likely to optimize such automatic variables -- that should explain why you are getting the same address. For brownie points, check if this is within the stack frame of main. Also, are you using any optimization flags? If your goal is overflow the stack, declare a large enough array of the structure. Also, a cast is necessary in order to print (w/o invoking UB) – dirkgently Aug 20 '10 at 05:51
  • @dirkgently - [Here it is](http://stackoverflow.com/questions/3156423/why-dont-we-use-void-in-main/3159563#3159563) - "It shall be defined with a return type of int and with no parameters ... or with two parameters ... or in some other implementation-defined manner ". (section 5.1.2.2.1) – detly Aug 20 '10 at 06:01
  • @dirkgently - void main accepted. "If your goal is overflow the stack, declare a large enough array of the structure" output is same. – Alam Aug 20 '10 at 06:02
  • @alam: That is an artifact of your implementation. E.g. `int main() { char j[ 10000000 ]; printf("%lu\n", (unsigned long)&j);` is good enough for me to get a fault. – dirkgently Aug 20 '10 at 06:16
  • 1
    @detly: See: http://www2.research.att.com/~bs/bs_faq2.html#void-main for an explanation of 5.1.2.2.1 – dirkgently Aug 20 '10 at 06:23
  • If I change a code bit from stack allocation to heap allocation. for e.g. struct infinite *infobj = (struct infinite *) malloc (sizeof (struct infinite)); ... then will there be any memory leaks? (My guess NO: same memory will be allocated again and again) – Alam Aug 20 '10 at 08:58
  • @alam memory will be leaked. And if you have not free-ed it, ultimately you should run out of memory. – KedarX Aug 20 '10 at 11:05
  • @dirkgently: C99 specifically allows "implementation defined behaviour" for the return type of main, so it is legal to use void main (depending on the implementation). 5.1.2.2.3 (Program termination) states "If the return type of the main function is a type compatible with int..." That phrase wouldn't be needed if main had to return int. Your link is simply wrong. – JeremyP Aug 20 '10 at 11:09
  • @dirkgently — interesting, but I don't see how it's consistent with the wording of the standard (unless I've taken that out of context, and it's only talking about the parameters?) – detly Aug 21 '10 at 09:08

2 Answers2

5

The infobj is destroyed at the end of each iteration of while loop, hence stack is not overflowing and you are getting the same address again and again. Whether you can allocate int arr[1000000] on the stack depends on the maximum allowed stack size per thread. On VC compiler this is 1 MB but can be changed through compiler options.

Naveen
  • 74,600
  • 47
  • 176
  • 233
  • that means my assumption for "STRUCT_MSG_SYS_HEADER sysHdr" stackoverflow is wrong? – Alam Aug 20 '10 at 05:41
  • @alam: Yes, the object is destroyed at the end of the loop. So the stack doesn't grow for each iteration of the loop. Hence you won't have stackoverflow. – Naveen Aug 20 '10 at 05:45
  • If I change a code bit from stack allocation to heap allocation. for e.g. struct infinite *infobj = (struct infinite *) malloc (sizeof (struct infinite)); ... then will there be any memory leaks? (My guess NO: same memory will be allocated again and again) – Alam Aug 20 '10 at 08:58
  • @alam: there will be memory leak. You are missing the point. The memory for the *pointer* will be allocated from stack, but the memory it is *pointing* is allocated from *heap*. The memory for the *pointer* will be released automatically at the end of loop but the memory it is *pointing* is still not released resulting in memory leak. You need to explictly `free` the memory so that the memory allocated on heap is released. – Naveen Aug 20 '10 at 09:13
4

No stack overflow will occur. That stack-allocated variable will only live for the duration of the loop iteration and after that stack space it occupies can be reused. Typically when the next iteration starts exactly the same space will be used for the variable in the new iteration.

Stack overflow could occur in case of deep recursive chain of calls of the same function because when the new call would start all the variables in the scope of the previous call would need to be retained, so the sapce would not be reused, but instead more stack space would be used for each new call. This is not the case in this question.

sharptooth
  • 167,383
  • 100
  • 513
  • 979
  • I'd add - there is guarantee that compiler will place `infobj` on stack, it is up to compiler where to place automatic variables. – qrdl Aug 20 '10 at 07:10
  • @qrdl: Actually there's no guarantee there is a stack - that's an implementation detail. The key here is the variable lifetime - since it ends so early space can be reused. – sharptooth Aug 20 '10 at 07:15
  • @sharptoon That's exactly what I wanted to write - the word "no" in front of "guarantee" somehow escaped. – qrdl Aug 20 '10 at 08:43
  • If I change a code bit from stack allocation to heap allocation. for e.g. struct infinite *infobj = (struct infinite *) malloc (sizeof (struct infinite)); ... then will there be any memory leaks? (My guess NO: same memory will be allocated again and again) – Alam Aug 20 '10 at 08:59
  • @alam: Definitely there will be memory leaks if you don't `free()` that memory later. When you `malloc()` memory it is marked as yours and no sunsequent `malloc()` calls will return that memory until you explicitly `free()` it. – sharptooth Aug 20 '10 at 09:18