Memory Management in C/C++: The Heap and the Stack
When a program is loaded into main memory, usually it will be organized into four areas of memory, called segments: the code segment, the data segment, the stack segment, and the heap segment.
- Code Segment: Sometimes also called the Text Segment. It contains the executable instructions (machine code). The code segment is typically read-only.
- Data Segment: Data segment is sub divided into two parts.
Initialized data segment: All the global, static and constant data are stored in the data segment
Uninitialized data segment: All the uninitialized global and static variables are stored in this segment, also called BSS segment.
- Heap Segment: When program allocate memory at runtime using calloc and malloc function, then memory gets allocated in heap.
- Stack Segment: Stack is used to store the local variables, function parameters, and other function-related information.
In the embedded system, the executable code is stored in the code segment, and the code segment is read-only and stored in ROM area. There are two type of data segment:read-write and read-only. The read-write data segments (rwdata or .rwdata) are stored in RAM area, since the values of variables can be altered at run time. The read-only data segment (rodata or .rodata) contains static constants rather than variables and stored in ROM area.
The Heap Segment
The heap segment (also known as the "Free store") is used for dynamic memory allocation at run time. In C/C++, when you use calloc() / malloc() function or new operator to allocate memory block, this memory is allocated in the application's heap segment. When a dynamically allocated variable is deleted by using free(), delete and delete, the memory is "returned" to the heap and can then be reassigned as future allocation requests are received.
There are no enforced pattern to the allocation and deallocation of blocks from the heap, therefore you can allocated a block at any time and free it at any time. This makes it much more complex to keep track of which parts of the heap are allocated or free at any given time.
The heap has advantages and disadvantages:
- Allocating memory on the heap is comparatively slow.
- Allocated memory stays allocated until it is specifically de-allocated (beware memory leaks) or the application ends.
- Dynamically allocated memory must be accessed through a pointer. De-referencing a pointer is slower than accessing a variable directly.
- The heap can have fragmentation when there are a lot of allocations and deallocations.
- In C/C++, data created on the heap will be pointed to by pointers and allocated with new or malloc respectively.
- Variable on the heap must be destroyed manually and never fall out of scope. The data is freed with delete, delete, or free.
- Can have allocation failures if too big of a buffer is requested to be allocated.
The Stack Segment
The stack segment is typically located in the higher part of memory. A "stack pointer (SP)" register in the CPU tracks the top of the stack; it is adjusted each time a value is "pushed" onto or "popped" from stack. The stack is a linear data structure in which items are added and removed in last-in, first-out (LIFO) order.
The stack has advantages and disadvantages:
- Allocating memory on the stack is comparatively fast in comparison to variables on the heap.
- Data created on the stack can be used without pointers.
- Memory allocated on the stack stays in scope as long as it is on the stack. It is destroyed when it is popped off the stack.
- All memory allocated on the stack is known at compile time. Consequently, this memory can be accessed directly through a variable.
- Because the stack is relatively small, it is generally not a good idea to do anything that eats up lots of stack space. This includes passing by value or creating local variables of large arrays or other memory-intensive structures.
- Can have a stack overflow when too much of the stack is used. (Mostly from infinite (or too much) recursion, very large allocations)
The stack has a limited size, and consequently can only hold a limited amount of information.For example, on PSoC Creator, the default stack size is 2KB (0x0800). If the program tries to put too much information on the stack, stack overflow will result. Stack overflow happens when all the memory in the stack has been allocated, so any further allocation begins overflowing into other segment of memory.
Stack overflow is generally the result of allocating too many variables on the stack, and/or making too many nested function calls. Overflowing the stack will generally cause a program or system to crash.
The Heap vs. Stack
- Both Heap and Stack are stored in RAM area.
- Variables on stack go out of scope automatically once their need is done. That means deallocation on stack is automatic. On heap, in regards to C and C++ we have to manually de-allocate where as high-level languages such as Java has garbage collection schemes.
- On stack, we can access variables without the need for pointers and hence its fast and that is the reason it is used to store local data, method arguments and the call stack etc all that which needs less amount of memory.
- You would use stack only when you know for sure how much memory for your data you would need even before compile time. On the other hand, we can use heap without us having to know for sure the amount of memory we need.
- In a multi-threaded program, each thread will have its own completely independent stack but they will share the heap. Stack is thread specific and Heap is application specific.