salimsaid
salimsaid

Reputation: 3495

Does the compiler reserve memory for the biggest block of code or all blocks in C?

Does the C compiler allocate all the memory required before running a program Or it does allocate memory for the biggest block of memory ? In both cases i am asking on statically allocated memory, i understand in dynamic memory allocation, memory is requested at runtime.

See below code

    #include <stdio.h>

    int global_flag = 1; //using 4 bytes

    void create_8_bytes()
    {
        /*
         * create 2 integers , total 8 bytes
        */
        int a = 3;
        int b = 6;

    }


    void create_4_bytes()
    {
        /*
         * 1 variable , total 4 bytes
        */
        int a  = 1;
    }

    void main()
    {
        create_8_bytes(); //8 bytes
        create_4_bytes(); //4 bytes
        puts("done");
    }

How much memory would be needed to run the above program ?

Upvotes: 3

Views: 245

Answers (2)

zneak
zneak

Reputation: 138061

In non-trivial C/C++ programs, it's generally not possible to know in advance how much memory you will need at runtime. That means that even if your compiler tried its hardest, it couldn't always produce a program that statically reserves just the right amount of memory.

Modern platforms generally differentiate at some level between three "types" of memory:

  1. the memory that your program allocates and uses for its entire duration (static/global variables, functions, etc)
  2. the memory that your program can request at runtime, using malloc and such
  3. the stack memory

The amount of static memory that your program needs can't easily be estimated, because it varies a lot depending on the operating system, the compiler, the standard library, etc. However, your program is very small, so it would be surprising if it needed more than a few kilobytes on any platform. On platforms where memory is particularly precious, it's likely that it could be just a few bytes.

Your program does not use malloc or other allocation functions, so it needs no such memory.

The stack memory is where the magic happens here. The stack is an area of memory that the program can use (and re-use) when a function is called. Its size depends on the platform (and it is usually documented somewhere), and operating systems typically optimize its use such that the memory isn't made available to the program before it actually tries to use it.

If you run out of stack memory, undefined behavior happens. On platforms where memory is precious, you're likely to corrupt some other area of your program. On most modern platforms these days, you'll get a crash instead.

Assuming that your program wasn't optimized, and glossing over some platform details, the memory use would look somewhat like this:

  • start of program
    • you use no stack memory
  • enter main: set up stack frame (~16 bytes of housekeeping)
    • you use 16 bytes of stack memory
  • enter create_8_bytes: set up stack frame (~16 bytes of housekeeping, 8 bytes of variables)
    • you use 40 bytes of stack memory
  • leave create_8_bytes: release the stack frame that create_8_bytes used
    • you use 16 bytes of memory
  • enter create_4_bytes: set up stack frame (~16 bytes of housekeeping, 4 bytes of variables)
    • you use 36 bytes of memory
  • leave create_4_bytes: release the stack frame
    • you use 16 bytes of memory
  • enter puts (use unknown amount of memory)
    • you use 16+??? bytes of memory
  • leave puts
    • you use 16 bytes of stack memory
  • leave main
    • you use no stack memory

As you can see, the amount of memory that you use grows and shrinks as you enter and leave functions.

Although this provides the right intuition for how stack memory is used, keep in mind that compilers are generally capable of removing parts of your program if they can prove that it won't change the outcome. This means that you could expect your local variables to disappear if you don't use them, and even if you do use them, it's possible that the compiler could use other transformations that would allow the variables to use no stack memory at all. It's also possible that the compiler could use stack memory for things that you haven't explicitly told it to.

Upvotes: 4

Blaze
Blaze

Reputation: 16876

Depends on the compiler, your environment, the OS, and other things. There's going to be an overhead that's much bigger than a couple of bytes anyway.

That aside, most of this program might be optimized away, so those ints may be irrelevant. The program can be reduced to nothing else than puts("done");.

Those ints would be on the stack. So create_8_bytes would cause the creation of a new stack frame that has space for the two ints (and more, such as the stack pointer, so again, the numbers will be off). Then, when create_8_bytes is done, its stack frame will be invalid and afterwards create_4_bytes is called, which makes a stack frame to hold that int. All of course assuming that nothing is inlined or optimized away.

What you probably wondered is whether the a and b from create_8_bytes and the a from create_4_bytes will "exist" at the same time. They won't. Of course, actual memory consumption won't represent that as the overhead of the function calls, the program itself (which includes loading the necessary code behind puts) and how the OS handles the memory allocation will in total be much more relevant that those twelve bytes. And if you're compiling a debug build, then all of it is going to be drastically different again, as the compiler doesn't optimize away things that it otherwise would, includes stuff in the program that it otherwise wouldn't and maybe even makes a sandboxed environment to run your program in that takes up megabytes for even the most simple application.

Upvotes: 2

Related Questions