Abstract


  • A list of memory locations from 0 to some maximum, which Process (进程) can access
  • Address space is powered by Virtual Memory, so everything in address space is dedicated to that particular process
  • 4 main components
    • Data in Text Segment (the orange block shown above) and Data Segment (the red block shown above) are shipped with the program
    • Data in Heap Segment (the blue block shown above) and Stack Segment (the green block shown above) are allocated dynamically when the program is running

Heap Segment


  • Data is added into heap segment explicitly by Process (进程) during runtime using System Call (系统调用) like brk() for Kernel that follow POSIX. The data in heap can live indefinitely even when function returns, the data is only removed when the process make the related System Call (系统调用) explicitly
  • Grows and shrinks as the process allocates and deallocates memory. The heap segment grows upwards, because the Memory Address is increasing as we have more data is allocated inside the heap segment

Bigbrain

When assigning one variable to another variable, data is not duplicated, instead the Pointer to the data inside the heap segment is duplicated and assigned. A nice visualisation on heap memory allocation can be found here.

Manual memory management from the process needed!

Process is responsible of allocating memory and deallocating in the heap segment. See language examples below.

Java

  • Memory allocation with new keyword, and memory deallocation is done by Garbage Collector automatically

Rust

C

  • Memory allocation with malloc() function, and manual memory deallocation is done with free() function

Manual Memory Deallocation is Dangerous!

After we manually deallocated the heap memory associated with a Pointer, then try to read data from the same pointer, it will lead to undefined behaviours. Thus, resulting in Poor memory safety.

Refer to this section of article for more details.

Heap fragmentation

  • There are 2 types of heap fragmentation - Internal Fragmentation & External Fragmentation(show in the diagram above)
Internal FragmentationExternal Fragmentation
DefinitionWhen allocated Memory frames have unused memory space, since each memory frame comes with a fixed size.When free memory frames in the heap are scattered throughout the memory space after a series of allocations and deallocations of memory blocks of varying sizes.
RiskIncreased memory consumption than actual demand.

For example, the memory frame size is 10MB, and my program needs 10.00001MB. We will get 2 memory frames that are 10MB each, this means 9.99999MB is wasted. Imagine I have a lot of programs with 10.00001MB in my computer, that means we waste almost half of the available Main Memory!
Difficulty to allocate contiguous blocks of memory reduced performance.

Small gaps between allocated blocks can also become unusable if Virtual Memory isn’t used, even though the total amount of free memory might be sufficient to fulfil a request.

Ways to handle memory fragmentation

Compaction - rearranging memory blocks to eliminate gaps.

And many other techniques like Dyanmic memory allocation - Wikipedia and Memory pool - Wikipedia.

Memory leak

  • Happens when we forget to release data in Heap Segment using free() in the example of C
  • This can eventually lead to the exhaustion of available Main Memory, resulting in degraded performance or even program crashes

Attention

We should always deallocate the chucks of data when we don’t need it anymore to avoid memory leak!

Stack Segment


  • Also known as Call Stack
  • Dynamically allocated region used to store function calls, local variables, and temporary data etc
  • Made up of Stack Frame, following a Stack structure
  • Expands as functions are called and shrinks as they return
  • We can obtain the default stack size assigned by the system using ulimit -s

Variables live in the stack

When assigning one variable to another variable, data is duplicated.

For example, a=1 and b=a, the value 1 is duplicated and assigned to b. A nice visualisation can be found here

Data management in Stack Segment is more efficient than Heap Segment

  1. Stack memory is allocated and deallocated in a Last In, First Out (LIFO) manner, making it faster than heap memory. This is because all it needs to do is move the Stack Pointer up or down, while heap memory requires more complex memory management
  2. No overhead of complex Synchronisation (同步), unlike data inside heap segment, data inside the stack segment is dedicated to that particular Thread. Thus, manipulation of data inside the stack segment doesn’t require the complex synchronisation

Attention

The size of variable on the stack is defined before Compilation

Stack Frame

  • A section of the Stack Segment dedicated to a specific function call
  • Except for the first frame, all frames contains the Memory Address of the previous stack frame, and the size of current stack frame which is used to adjust the Stack Pointer to exclude the current stack frame from the stack segment when the function call of the current frame ends. The current stack frame will be overwritten when a new frame is added to the stack segment

Stack Overflow

  • Happens when the size of all the stack frame is over the default fixed size of the stack segment. Usually can be triggered easily without a proper implementation of Recurrence Function

Data Segment


  • This region stores global and static variables and constants used by the program, pre-defined before the execution of the program
  • Can be both read and write, allowing the Process (进程) to manipulate the data as needed

Text Segment


References