Program execution

When2 a program is loaded into memory, it is organized into three areas of memory, called segments: the text segment, stack segment, and heap segment. The text segment (sometimes also called the code segment) is where the compiled code of the program itself resides. This is the machine language representation of the program steps to be carried out, including all functions making up the program, both user defined and system.

The remaining two areas of system memory is where storage may be allocated by the compiler for data storage. The stack is where memory is allocated for variables within functions. A stack is a Last In First Out (LIFO) storage device where new storage is allocated and deallocated at only one ``end'' (the top of the stack).

Every C/C++ program begins executing at a function called main(): space is allocated on the stack for all variables declared within main(). If main() calls a function, say myFunction(), additional storage is allocated for the variables in myFunction() at the top of the stack. Notice that the parameters passed by main() to myFunction() are also stored on the stack. If myFunction() were to call any additional functions, storage would be allocated at the new top of stack. When myFunction() returns, storage for its local variables is deallocated, and the top of the stack is resumed at the old position. As can be seen, the memory allocated in the stack area is used and reused during program execution. It should be clear that memory allocated in this area will contain garbage values left over from previous usage.

The heap segment provides more stable storage of data for a program; memory allocated in the heap remains in existence for the duration of a program. Manually allocated memory, global and static variables are allocated on the heap.

On many architectures, including Intel-based PCs, the relative order of text and stack segment is such that the text segment is placed after the stack segment. This means that if one uses a variable stored on the stack to hold an array of bytes longer than the stack itself, one ends up overwriting parts of the text segment. Since the text segment contains the executable machine code instructions, it is theoretically possible to change the behaviour of the computer by simply entering some meaningful data in a variable. This was the technique used by some of the most spectacular network hacks of the eighties and nineties (see http://insecure.org/stf/smashstack.html).

The death of a process can occur by explicit program termination (returning from the main() function, use of the exit() system function) or by an operating system signal occurring because of some extraordinary condition. The most common are user intervention (SIGINT, SIGKILL) and runtime errors (SIGSEGV -- segmentation violation -- when the process tries to read or write memory that does not belong to it). When the process terminates, it is removed from the process table along with all the memory it occupies, and its ID becomes available for new processes.

Leo Liberti 2008-01-12