Research Interests
Direct Links
Relevant Links

 

Process Memory

This page give some basic explanation about the different types of the memory used by each process in Windows. I do not intend to be very precise. Some processes are quite simplified. I just want to be useful.

This section may be important to those who write or use resource consuming applications and want them to be efficient and safe.

Why RAM is not the only thing you should care about

People tend to relate lack of memory problem to insufficient RAM. This is not necessary true. In fact, this is usually not true. This stopped to be true when we stopped using DOS and switched to Windows (especially the NT family).

How Windows Handles Memory

Windows prevents processes from accessing physical RAM directly (remark: this is true for processes executed at user mode. You could embed a process into Kernel and access RAM directly, but then, strictly speaking it becomes part of Windows). Each process operates within virtual memory address space. In other words, each process only "thinks" it accesses RAM at some address. In fact, this is just number used by OS to compute the actual physical address. This redirection is performed every time you access RAM from your process.

Why is it done? For many reasons. First of all, to prevent one process to interfere with other processes. For example, no number in your process could possibly cause Windows to access memory belonging to another process. Therefore, one can not hurt or crash another processes or Windows itself (remember Windows 3.x?)

Another good reason is flexibility. Detachment of the process memory from the actual physical RAM allows Windows to relocate the actual data behind your back. This is necessary for simultaneous execution of multiple processes. When some of them are inactive, the memory allocated by them is moved to disk (swap file).

The last reason I'll list here is about memory allocation (more on that in MS Windows x64. Why?). Virtual memory allows Windows to spot illegal memory access. It traces memory allocation done by your process and can shout the moment you try to access anything outside legally allocated space (remember, every memory access goes though the OS).

Memory types

Each process receives a single chunk of virtual memory. In general, it is split into three regions corresponding to the three types of memory your code uses. Windows must know in advance how to split all virtual memory between the memories. There are some defaults, but usually, the quantities are listed within the executable itself (in the so-called PE file header). The application may crash even if you have plenty of RAM left on your machine or even if your have plenty space in your virtual environment. It's sufficient that it lacks one of the necessary memory sections. How? Let's look into some details and see few cases.

There is some space allocated by the operating system (OS) for the code itself. There, it keeps the instructions processed by the CPU. This is rarely a problem since the code does not take much space and most importantly, it's size is known in advance and does not change at run time.

Stack

There is some space allocated by the process for stack. Function variables and some system information are kept in stack. If a function is called by another function, a new frame on stack is allocated for that function's local variables. That new frame is freed when the function returns and the previous frame becomes active. In fact, each frame represents local scope. These scopes are nested in exactly the way, the method calls are nested.

What effects the required stack size? The more local variables and nested calls you have, the more of the stack your code consumes. It's very dynamic and hard to trace. When exceeded, your application crashes with "0xC00000FD: stack overflow" error (remember, Windows can trace your code execution).

Here's a short example. The following code requires above 256 bytes for each stack frame (256 bytes for the array plus few extra bytes for the maintenance.

 void f(int Deapth)

 {

  if (Deapth==1000) { return; }

   char Str[256];

   f(Deapth+1);

 }

So, if called with Deapth equals 0, the function will consume above 256 KB of stack space (unless a smart compiler optimizes the Str variable as not used.

Controlling Stack Size

There are few ways available for you to control stack size.

  • The best and smartest one - check your algorithm. You are probably overusing recursive calls. Remember: any recursive algorithm can be converted to iterative one.
  • Allocate memory on heap (see below).Unlike stack, heap is controlled by you. It's dynamic. If you allocate your array dynamically, only the pointer is kept on stack. The array itself is allocated in heap. For example: int *p_array = new int[1000]; puts one variable (p_array) on stack and 1000 - in heap. Moreover, those 1000 variables will be available even when the allocating them method returns (which puts the headache of their release on the user shoulders). On the contrary, int array[1000]; places the 1000 variables on stack consuming it's valuable space.
  • The last choice is increasing the space allocated for stack. This can be done in two ways.
    • The linker can be instructed to place the specified stack size into the PE file header. This is usually done via link options. MS Visual C++ uses /STACK switch to archive that.
    • If the source of the problematic code is not available or the code is a DLL (only executables, starting the process have control over the stack size), the Microsoft's EDITBIN.EXE tool can be used to alter the executable.

Application to MatLab

I have encountered a stack overflow problem with MatLab. One of my mex-files went into deep recursion and exceeded the stack size requested from Windows by MatLab executable. The MatLab didn't handle stack overflow correctly and just crashed without any notice or error report.

It turned out that MatLab 2006b and 2007a are configured to utilize 8MB for the stack. Increase of this quantity to 32MB solved the problem (I used EDITBIN.EXE ). You should, however, keep in mind that each time MatLab starts, it allocates the specified amount of RAM for the stack (which has some implications for the RAM consumption and startup time).


Footer