11

Why do books say, "the compiler allocates space for variables in memory". Isn't it the executable which does that? I mean, for example, if I write the following program,

#include <iostream>
using namespace std;

int main()
{
   int foo = 0;
   cout<<foo;
   return 0;
}

and compile it, and get an executable (let it be program.exe), now, if I run program.exe, this executable file will itself command to allocate some space for the variable foo. Won't it ? Please explain why books keep on saying, "the compiler will do this...do that" whereas actually, the compiled executable does that.

Adding another related question to this question, why is sizeof called a compile-time operator ? Isn't it actually a run-time operator ?

3
  • it's a bad example. foo is not used and will be eliminated during compilation.
    – Abyx
    Commented Apr 18, 2013 at 10:17
  • @Abyx Man, try to understand my question. The focus is not on whether the var is used. Anyway, I edited the program for you.
    – Shravan
    Commented Apr 18, 2013 at 11:05
  • man, actually nothing changed with that edit. =)
    – Abyx
    Commented Apr 18, 2013 at 11:06

7 Answers 7

20

When we hire an architect to design a house, he or she defines the size of the rooms, etc. and informs the workers (labourers) about it. The labourers do the work accordingly. But still we would say "The architect made the house this way" and not "The labourer made the house this way".

The labourer is just performing the steps defined by the architect. The compiler actually does all the work for checking and defining how much memory is to be allocated, etc. at run time and then those instructions are just followed.

0
11

Technically the act of creating the space itself is done at run time, however the compiler is the one to figure out how much space to reserve on the stack in your case, for your foo variable.

The compiler knows the size of the int type and therefore can generate the right assembler instruction that will reserve enough space on the stack in order to let foo live there.

If you look at the below generated assembler (using MSVC2012) for the program you showed, I have commented some of it to show you what happens:

#include "stdafx.h"
#include <iostream>
using namespace std;

int main()
{
//Setup stack frame for main by storing the stack pointer from the calling function and 
//reserving space for local variables and storing commonly used registers on the stack
002E4390  push        ebp  
002E4391  mov         ebp,esp  
// reserve space for local variables, which is 204 bytes here, no idea why so much.
// this is where the compiler calculated the size of your foo and added that to whatever else needs to be stored on the stack. Subtract from stack pointer (esp) because stack grows downward.  
002E4393  sub         esp,0CCh  
002E4399  push        ebx  
002E439A  push        esi  
002E439B  push        edi  
002E439C  lea         edi,[ebp-0CCh]  // load effective address of [ebp-0CCh], which I suspect would be your foo variable into edi register
002E43A2  mov         ecx,33h  
002E43A7  mov         eax,0CCCCCCCCh  
002E43AC  rep stos    dword ptr es:[edi]  //fill block of memory at es:[edi] with stuff  
   int foo;
   return 0;
002E43AE  xor         eax,eax  //set eax to zero for return value
}
// restore everything back to how it was before main was called
    002E43B0  pop         edi  
    002E43B1  pop         esi  
    002E43B2  pop         ebx  
    002E43B3  mov         esp,ebp  
    002E43B5  pop         ebp  
    002E43B6  ret  
8
  • 1
    An interesting question here is why the compiler allocates 204 bytes for local variables, when all it needs is 4. (You used VC++ here, but I've noticed several compilers which seem to allocate a lot more than is needed.) Commented Apr 4, 2013 at 8:44
  • @JamesKanze, I have wondered that. I am not sure why it seems to allocate that much. Commented Apr 4, 2013 at 8:46
  • 2
    @JamesKanze I asked a question asking this: stackoverflow.com/questions/15806673/… because I'm curious as to why this would be. I mentioned you in it Commented Apr 4, 2013 at 8:57
  • 1
    @Abyx I think for showing what happens in this case it doesn't really matter. Commented Apr 18, 2013 at 10:19
  • 4
    @Abyx You are missing the point. Completely. The idea was to describe to the OP how the compiler generates the assembly which describes the memory requirements of a given program. Not the specific one, nor to describe optimization possibilities and approaches.
    – user1309389
    Commented Apr 18, 2013 at 11:16
8

It's just a loose use of terminology. Of course the compiler doesn't allocate memory for the program. A more accurate description is that it tells the runtime how much memory to allocate when the program is running.

Until the program is actually run, it isn't in memory (unless it's loaded dynamically, but even that happens during run-time, so out of the scope of the compiler), so there's no memory to speak of.

What those books are talking about is allocating variables whose size is known at compile-time, as opposed to dynamic allocation cin >> x; int * y = new[x];, where the size isn't known.

3

It says the compiler allocates space for variables in memory, because otherwise you need to allocate (and free!) memory yourself with new/malloc etc.

1
  • 2
    and it won't be compiler then? you gonna to just write it on a piece of paper? ; p
    – 4pie0
    Commented Apr 4, 2013 at 8:23
2

Of course compiler doesn't "allocate space for variables". Compiler generates a code which allocates space for variables in memory.

I.e. if you have

int foo;
foo = 1;

in source code, compiler may generate a code like

int* fooPtr = allocate sizeof(int)
*fooPtr = 1;

In the x86 architecture, usually that allocate thing will be a single assembly instruction:

sub esp, 4    ; allocate 4 == sizeof(int) bytes on stack
              ; now the value of "esp" is equal to the address of "foo",
              ; i.e. it's "fooPtr"
mov [esp], 1  ; *fooPtr = 1

If you have more than one local variable, compiler will pack them into a structure and allocate them together:

int foo;
int bar;
bar = 1;

will be compiled as

struct Variables { int foo; int bar; };
Variables* v = allocate sizeof(Variables);
v->bar = 1;

or

sub esp, 4+4       ; allocate sizeof(Variables) on stack
mov [esp + 4], 1   ; where 4 is offsetof(Variables, bar)
0

The compiler generates machine instructions and works out what memory address local variables will occupy. Each local variable is given an address relative to the top of the stack, eg foo would be assumed to be at memory address stack_pointer. If you had a variable foo2 it would be placed at address stack_pointer + 4 where 4 is the size of an int.

When the local variable foo is accessed, the compiler will substitute the address held in stack_pointer. The hardware has a special stack_pointer register which always points to the top of the current stack.

The compiler knows what size each variable is because it is responsible for looking at struct or class declarations and working out how it is laid out in memory. So sizeof is known at compile time and is treated as a constant expression. Primitive types like int are known to be of a certain size, eg sizeof(int) is 4.

-1

Suggest you to read compiler construction. Focus on the storage phase, your query would be resolved.

After the program gets compiled its converted to object code, which is an assembly language code. every line of a high level language program gets translated to many assembly language steps. The translated program is put into the assembler which is executed. There is STORAGE assignment phase in comiler construction which translates to Machine Operation table(MOT instructions at assembly level). This is where space allocation for variables/registers is done. There is a register modifier keyword in C++ as well.

4
  • 1
    This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post - you can always comment on your own posts, and once you have sufficient reputation you will be able to comment on any post.
    – Nico O
    Commented Mar 27, 2014 at 10:26
  • After the program gets compiled its converted to object code, which is an assembly language code. every line of a high level language program gets translated to many assembly language steps. The translated program is put into the assembler which is executed. There is STORAGE assignment phase in comiler construction which translates to Machine Operation table(MOT instructions at assembly level). This is where space allocation for variables/registers is done. There is a register modifier keyword in C++ as well.
    – DevK
    Commented Mar 27, 2014 at 10:51
  • i know Nico O.. Kindly ask for clarity in user comments if you don't happen to understand other's answer/perspective. Once the author is aware about compiler construction process, he'll understand thats its object code that does work. Compiler is a mere code generator to lower level of programming code.
    – DevK
    Commented Mar 27, 2014 at 11:05
  • -1. What you're saying has nothing to do with the question. That applies to the comments, too. Commented Mar 27, 2014 at 11:37

Not the answer you're looking for? Browse other questions tagged or ask your own question.