Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
399 views
in Technique[技术] by (71.8m points)

c - Memory allocation for global and local variables

I have learnt that memory for global variables are allocated at program startup whereas memory for local variables are allocated whenever function call is made.

Case 1:
I have declared a global integer array of size 63500000 and memory used is 256 MB
Ideone Link

include <stdio.h>
int a[63500000];
int main()
{
    printf ("This code requires about 250 MB memory
");
    return 0;
}

Case 2:
I have declared a local integer array of same size in main() and memory used is 1.6 MB
Ideone link

#include <stdio.h>
int main()
{
    int a[63500000]= {1,5,0};
    printf ("This code requires only 1.6 MB 
");
    //printf ("%d
", a[0]);
    return 0;
}

Case 3:
I have declared a local integer array of same size in another function and memory used is 1.6 MB
Ideone Link

#include <stdio.h>
void f()
{
    int a[63500000];
}

int main()
{
    f();
    return 0;
}

Please explain why there is difference in memory used or my concept of memory allocation is wrong ??

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

First of all: the ideone compiler is GCC.

So, what does GCC do when you compile this?:

void foo ()
{
  int a[63500000];
}

gcc -S -O2 foo.c generates:

foo:
    pushl   %ebp
    movl    %esp, %ebp
    popl    %ebp
    ret

i.e. nothing is allocated on the stack, at all.

The array is simply optimized away by GCC because it is never used.

GCC won't do this with a global, because it is possible that a global is used in another compilation unit, and so it isn't sure that it is never used. Also: The global is not on the stack (since it is a global).

Now, lets see what happens when you actually use the local array:

int bar (int a, int b, int c)
{
  int f[63500000];
  f[a] = 9;
  f[b] = 7;
  return f[c];
}

Things are very different:

bar:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $254000000, %esp
    movl    8(%ebp), %eax
    movl    $9, -254000000(%ebp,%eax,4)
    movl    12(%ebp), %eax
    movl    $7, -254000000(%ebp,%eax,4)
    movl    16(%ebp), %eax
    movl    -254000000(%ebp,%eax,4), %eax
    leave
    ret

This line: subl $254000000, %esp corresponds to the size of the array. i.e. memory is allocated on the stack.

Now, what if I tried to use the bar function in a program:

int bar (int a, int b, int c)
{
  int f[63500000];
  f[a] = 9;
  f[b] = 7;
  return f[c];
}

int main (void)
{
  return bar (0, 0, 0);
}

We already saw, that the bar function allocates 250 or so megabytes on the stack. On my default GNU/Linux install, the stack size is limited to 8MB. So when the program runs, it causes a "Segmentation fault". I can increase it if I want, by executing the following in a shell:

ulimit -s 1000000 #i.e. allow stack size to grow close to 1GB

Then I can run the program, and it will indeed run.

The reason why it fails on the ideone website is that they have limited the stack size when executing programs (and they should, otherwise malicious users could mess up their system).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...