Alex Rivera | Logout

How is the stack initialized?

Asked 2011-03-10T21:41:37.823
17

When a process requests for memory and an operating system is giving some new pages to the process, the kernel should initialize the pages (with zeros for instance) in order to avoid showing potentially confident data that another process used. The same when a process is starting and receives some memory, for example the stack segment.

When I execute the following code in Linux, the result is that the majority of allocated memory is indeed 0, but something about 3-4 kB at the bottom of the stack (the last elements of the array, the highest addresses) contains random numbers.

#include <cstdlib>
#include <iostream>
using namespace std;

int main()
{
    int * a = (int*)alloca(sizeof(int)*2000000);
    for(int i = 0; i< 2000000; ++i)
        cout << a[i] << endl;
    return 0;
}
  1. Why isn't it set to zero too?
  2. Could it be because it is being reused by the process?
  3. If yes, could it be the initialization code that had used those 3-4 kB of memory earlier?
Edit
Report

2 Answers

13

The operating system does not guarantee a zero'ed out memory, just that you own it. It will probably give you pages of memory that were used before (or never used before, but non-zero). If an application stores potentially-sensitive data, it is expected to zero it before free()'ing.

It's not set to zero because that would be performing unnecessary work. If you allocate 20 megabytes to store a texture or a few frames of video, why would the OS write zeroes to all that memory just so you can overwrite them as the very next thing you do.

As a general rule, operating systems don't do anything that they don't have to.

edit: to expand a little bit, when you "allocate" a block of memory, all the OS is doing is re-assigning pages of memory (blocks of 4096 bytes, typically) to your process from a pool of un-allocated pages. You can also have shared memory, in which case the OS 'assigns' them to multiple processes. That's all allocation amounts to.

answered 2011-03-10T21:44:48.100
3

The top of the stack contains the environment variable definitions and below them are the command line arguments and the environ and argv arrays.

On an x86_64 a simple startup code under Linux could look like:

asm(
"       .text\n"
"       .align  16\n"
"       .globl  _start\n"
"       .type   _start,@function\n"
"_start:\n"
"       xor     %rbp, %rbp\n"           // Clear the link register.
"       mov     (%rsp), %rdi\n"         // Get argc...
"       lea     8(%rsp), %rsi\n"        // ... and argv ...
"       mov     %rax, %rbx\n"           // ... copy argc ...
"       inc     %rbx\n"                 // ... argc + 1 ...
"       lea     (%rsi, %rbx, 8), %rdx\n"// ... and compute environ.
"       andq    $~15, %rsp\n"           // Align the stack on a 16 byte boundry.
"       call    _estart\n"              // Let's go!
"       jmp     .\n"                    // Never gets here.
"       .size   _start, .-_start\n"     
);

Edit:

I completely misread the question. The stuff at the top of the stack in your code is probably the result of the startup code called before main() is entered.

answered 2011-03-10T21:48:49.983

Your Answer