Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where is local variable allocated? Heap or stack?

http://www-ee.eng.hawaii.edu/~tep/EE160/Book/chap14/subsection2.1.1.8.html This page says local variables and parameters passed are allocated on stack, So I tried:

#include <stdio.h>
#include <stdlib.h>
#define A 2000000
#define B 2

typedef struct {
    int a[A][A];
} st;

void fun(st s){}

void main()
{
    st s;
    //fun(s);
}

No error reported after compiled and run. But when I de-annotate //fun(s) , Then SIGSEGV is caught. Can anyone tell why?

like image 832
CDT Avatar asked Jan 26 '13 02:01

CDT


2 Answers

Where is local variable allocated? Heap or stack?

This page says local variables and parameters passed are allocated on stack

Exactly.

But when I de-annotate //fun(s) , Then SIGSEGV is caught. Can anyone tell why?

Memory on the stack is much more limited than on the heap¹. You're allocating a 2000000x2000000 array on the stack and then passing it to a function. This is very likely to exceed the available stack space, causing a segmentation fault.

As for why the segmentation fault doesn't happen when the function call is commented out. First of all, as Jonathan Leffer pointed out, the compiler will probably optimize s away completely because it isn't used. But even if it didn't, you might not get a segfault because allocating memory on the stack just means incrementing the stack pointer. And on most implementations that itself will never cause a segmenetation fault. The segmentation fault will only happen once you try to access the allocated memory and the system realizes you're exceeding the bounds of the stack (and in this case of the entire memory as well).

¹ Though in this case that doesn't make a difference because, as slugonamission pointed out, the array takes up 16TB and thus would exceed the available memory on the heap as well.

like image 182
sepp2k Avatar answered Oct 04 '22 16:10

sepp2k


In addition, that is a good example why you merely pass a function argument by value and usually you pass argument by reference:

#include <stdio.h>
#include <stdlib.h>
#define A 2000000
#define B 2

typedef struct {
    int a[A][A];
} st;

void fun(st *s){}

void main()
{
    st s;
    fun(&s);
}

I don't think it will run at all since it requires a 4TB of memory on stack. And it compiled and run smoothly with //fun(s) in your code since the unused s variable dumped by the compiler and wasn't declared at all on run time.

like image 42
0x90 Avatar answered Oct 04 '22 15:10

0x90