Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C heap address changes between runs while other addresses persist

The heap troubles me because I don't understand who creates it, who maintains it and who decides where it should be... This test shows part of my conundrum:

Source code:

#include <malloc.h>
#include <stdio.h>

int a;
int b = 5;

int * getMeAPointer() {
    int * e = malloc(4);
    *e = 5;
    return e;
}


void main() {
    a = 5;
    int c = 5;
    int * d = (int *) 0x405554;
    *d = 5;
    int * e = getMeAPointer();
    printf("Address of a located in .bss is %x\n", &a);
    printf("Address of b located in .data is %x\n", &b);
    printf("Address of c located in stack is %x\n", &c);
    printf("Address of d located in stack is %x\n", &d);
    printf("Address of *d located absolutely is %x\n", d);
    printf("Address of e located in stack is %x\n", &e);
    printf("Address of *e located on heap is %x\n", e);
    printf("Address of getMeAPointer() located in .text is %x\n", getMeAPointer);
    free(e);
}

Example printouts:

Address of a located in .bss is 0x405068
Address of b located in .data is 0x402000
Address of c located in stack is 0x22ff1c
Address of d located in stack is 0x22ff18
Address of *d located absolutely is 0x405554
Address of e located in stack is 0x22ff14
Address of *e located on heap is 0x541738
Address of getMeAPointer() located in .text is 0x4013b0

Address of a located in .bss is 0x405068
Address of b located in .data is 0x402000
Address of c located in stack is 0x22ff1c
Address of d located in stack is 0x22ff18
Address of *d located absolutely is 0x405554
Address of e located in stack is 0x22ff14
Address of *e located on heap is 0x3a1738
Address of getMeAPointer() located in .text is 0x4013b0

Address of a located in .bss is 0x405068
Address of b located in .data is 0x402000
Address of c located in stack is 0x22ff1c
Address of d located in stack is 0x22ff18
Address of *d located absolutely is 0x405554
Address of e located in stack is 0x22ff14
Address of *e located on heap is 0x351738
Address of getMeAPointer() located in .text is 0x4013b0

....etc....

Now these are my concerns:

  1. Why is the heap moving around and none of the other segments? This is on a Windows 7 OS with MinGW and this file was compiled with GCC without further flags (I don't believe this is an example of Address Space Layout Randomization).

  2. Who decides where the heap should be? I belive the linker reserves a place for the heap (I've seen heap symbols in symbol tables) but when is the exact address decided on, is it a runtime thing done by the RUNNABLE itself (C code) AFTER loading, or is it done by the linker / loader / dynamic linker while LOADING the program right BEFORE execution?

  3. Is there any way to set the heap address in ld? I have understood that I can set all segments except stack (since that's built into the kernel of the OS) but can I set the heap address?

  4. The way I understands it, the heap is not really an assembly language construct and we don't have access to a heap if we choose to just do assembly programming. Therefore it is a C construct but I'm interested in how that affects the life of the heap (i mean we speak of the heap like it's on the same level as the segments and the stack but if it isn't, then that should give it a whole lot of other conditions)... is this correct and can anyone tell me something more about it?

I've Google'd all day long to be honest and I'm hungry for some answers!

like image 263
fast-reflexes Avatar asked Mar 08 '14 21:03

fast-reflexes


1 Answers

Why is the heap moving around and none of the other segments?

Because dynamic memory allocation is, well, dynamic. The address you get back from malloc() depends on where a sufficiently big chunk of free memory can be found at the very moment your program is being executed. Obviously, since there are other programs too, this changes over time.

Who decides where the heap should be?

The developers of your operating system.

I belive [sic!] the linker reserves a place for the heap

Rarely. On most implementations I've seen, it's entirely a runtime thing. (It's not that it's impossible that the linker have something to do with it, but still.)

Is there any way to set the heap address in ld?

If there is, it's surely documented. (Assuming that the ld you are referring to is the linker in your toolchain.)

[...] I can set all segments except stack (since that's built into the kernel of the OS)

I don't think I fully understand what you are saying, but "the stack" is not "built in to the kernel". Generally, the stack address is either statically hard-coded into the executable or it is referred to using relative instructions.

the heap is not really an assembly language construct and we don't have access to a heap if we choose to just do assembly programming.

But yes you do. I'm not familiar with Windows, but on most Unixes, you can use the brk() and/or sbrk() syscalls.

Therefore it is a C construct

Your logic is flawed. Just because something is not an assembly thing, it does not automatically mean that it's a C thing. In fact, there's no such thing as "the heap" or "the stack" in C. In C, there is only automatic, static and dynamic storage duration, which are not tied to specific manners of implementation.

like image 101
user3383733 Avatar answered Sep 29 '22 08:09

user3383733