Program memory layout in linux
Asked Answered
S

2

12

I am a bit confused on how a program looks like in memory , my professors told me that the stack and heap grow towards each other with the stack being at a lower memory address.

First thing that bothered me with that image is that if the heap grew from high to low then if I allocated an array on the heap shouldn't a pointer to the second element be smaller in int value than a pointer to the first element ? which would be confusing

I did a little research and I came upon this figure (note my question is focused on linux)

layout
(source: cyberplusindia.com)

Ok, so Data and un-initialized data comes after the Text segment and are in the beginning of the program's memory then the heap followed by the stack and finally the command line arguments and environment.

But if the stack grows from high addresses to low then how come if I have an array allocated on the stack a pointer to the first element will also be lower in value than a pointer to the second element ? doesn't that mean the stack would grow from low to high also ?

So my question is what is the correct memory layout for a process in Linux? And also where does the memory for a shared library come from (in the process' address space)

Simple code with pointer examples :

#include <iostream>


int data[5];

int main()
{
  using std::cout;
  using std::endl;
  int stack = 0;
  short *sptr = reinterpret_cast<short *> ( &stack );
  int *iptr = new int[5];
  cout << "Starting static tests"
       << "\nPointer to first element " << data
       << "\nPointer to second element " << &data[1]
       << "\nstarting stack test " <<  sptr
       << "\nsecond short " << &sptr[1]
       << "\nStarting heap test " << iptr
       << "\nsecond int " << &iptr[1];
  delete[] iptr;
  return 0;
}

Output:

Starting static tests
Pointer to first element 0x6013e0
Pointer to second element 0x6013e4
starting stack test 0x7fffdf864dbc
second short 0x7fffdf864dbe
Starting heap test 0x1829010
second int 0x1829014
Smoothshaven answered 14/7, 2013 at 0:37 Comment(0)
S
3

if I have an array allocated on the stack a pointer to the first element will also be lower > in value than a pointer to the second element ?

It is not important "how" you allocate the array, you can increase or decrease the stack pointer, but as result you have address space reserved for the array.

You can work with them in normal way, since the lowest adress is reserved for element 0.

so my question is what is the correct memory layout for a process in Linux ?

You can check it yourself. Insert somewhere into you program something like std::cin.get() to pause your program.

Then run in a separate shell:

ps aux | grep your_program_name
cat /proc/<pid show by grep>/maps 

This prints the memory mappings of your process, where you can see where the heap, the stack and other things are placed in memory.

About the stack: let's assume that you have ordinary machine with Linux and Intel or AMD 64 bit CPU. Then write the following code:

extern void f(int);

void g(int param)
{
    f(param);
}

compile it and disassemble:

g++ -ggdb -c test_my_stack.cc  && objdump -S test_my_stack.o

you can see (unimportant details removed):

 void g(int param)
 {
 0:   55                      push   %rbp
 1:   48 89 e5                mov    %rsp,%rbp
 4:   48 83 ec 10             sub    $0x10,%rsp
 8:   89 7d fc                mov    %edi,-0x4(%rbp)
    f(param);
 b:   8b 45 fc                mov    -0x4(%rbp),%eax

as you can see in sub $0x10,%rsp we reserved space in the stack by decreasing (moving down) the stack pointer.

Stingaree answered 14/7, 2013 at 0:51 Comment(6)
I checked out the maps of the example program in my question and unless I am reading it wrong both the stack and heap grow from low to high 016ea000-0170b000 rw-p 00000000 00:00 0 [heap] 7fffe828a000-7fffe82ab000 rw-p 00000000 00:00 0 [stack] with lots of .so in the middle and I can't seem to find the place reserved for environment and CLA gist with mapSmoothshaven
yeah I totally forgot about the whole esp so that should mean it grows from high to low, but how come when I create a short pointer to an integer created on the stack the first short is still lower address than second ? or am I missing something?Smoothshaven
Because of generated by compiler code not allocate stack per value, it allocate all at once. For your program it let's say allocate 0x50 bytes, then it say hey "stack" variable is "-0x34(%rbp)", "sptr" is -0x8(%rbp), so (uint8_t *)&stack < (uint8_t *)&sptr. This is because of it decrease stack pointer only once per function.Stingaree
ok so from the gist I linked I can see the invalid page just above the stack , the stack itself is only like 130kB long and the stack pointer goes from high to low does that mean if I reach a point where I need more than 130kB of stack it will grow towards the invalid page ? while the heap would grow from low to high till it hits the first .so ?Smoothshaven
As for stack, yes, if you use stack a lot you program crashed (SIGSEGV). You can try it by wrote program with recursion. But you can change limit with help of setrlimit, see #2279552Stingaree
About heap. On linux glibc (C runtime library) increase heap by requesting more space by two ways - sbrk and mmap. So if it is possible heap will be contiguous space, but if sbrk fail, still possible to create heap with holes with help of anonymous mmap. So part of heap can be in any unused places of adress space.Stingaree
D
3

First thing that bothered me with that image is that if the heap grew from high to low then if I allocated an array on the heap shouldn't a pointer to the second element be smaller in int value than a pointer to the first element ? which would be confusing

Not at all. Let's say you allocate an array of 10 bytes from a pool of memory that grows from high to low. All the allocator would have to do is decrement the "bottom" of that pool of memory by 10, then use that value as the start of the allocated array. The array would then end at the old "bottom". Pointer arithmetic would still work as expected, but you would "grow" towards low address.

Dredger answered 14/7, 2013 at 0:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.