Today, I am going to explore another useful concept of CPU memory management. I hope you all are enjoying my buffer overflow exploitation post.
So, Let's Start Our Tutorial
Virtual Memory Model In CPU Architecture.
In Today's Computer, Virtual memory is like the base of all function. Basically, Virtual Memory is a concept where every all running program or process feels like it is working alone in whole computer main memory but actually, under the hood every process is laid out in the same physical main memory. In Simple Words, Virtual Memory is a Concept where CPU and OS work together to create a special illusion for programs, in this illusion all working programs feel that it is in the system alone and enjoy all the memory without sharing with other processes. I hope you got the basic concept of virtual memory. Now, let me show you a diagram, which represents the virtual program memory environment created by CPU and OS for all program.
As You can see in above diagram, the top portion is denoted as highest address and the bottom portion is denoted as the lowest address. Ok ,
Now let's explore more point represented in this diagram.
High Address :
Actually, virtual memory layout always starts from bottom to top. hence, the physical address of the highest point in virtual memory represented as 0xBFFFFFFF
The stack is the memory set aside as empty space for a thread of execution. whenever a function is called, a data block is reserved on the top of the stack for local variable and when that function returns, the block becomes unused ad can be used the next time a function is called. Basically, stack works like a book shell where we can keep books for specific times. The stack is always reserved in a LIFO (last in first out) order, the most recent block is always the next block the be freed. This feature makes the stack more faster and simple to manage. (Most Important Point: So, I going to explain it separately.)
As Memory Segment name highlighting, This Segment is for unused memory.
heap is a Dynamic Memory.
Basically, This Segment is for storing Uninitialised Value.
This Segment is for storing initialize value.
This segment of virtual memory is for storing program executable instruction codes.
The physical address of lowest Point in virtual memory layout can be represented as 0x848000
The stack often works in close tandem with a special register on the CPU named the stack pointer. Initially, the stack pointer points to the top of the stack (the highest address on the stack).
The CPU has special instructions for pushing values onto the stack and popping them back from the stack. Each push stores the value at the current location of the stack pointer and decreases the stack pointer. A pop retrieves the value pointed to by the stack pointer and then increases the stack pointer (don't be confused by the fact that adding a value to the stack decreases the stack pointer and removing a value increases it. Remember that the stack grows to the bottom). The values stored and retrieved are the values of the CPU registers.
When a function is called the CPU uses special instructions that push the current instruction pointer, i.e. the address of the code executing on the stack. The CPU then jumps to the function by setting the instruction pointer to the address of the function called. Later, when the function returns, the old instruction pointer is popped from the stack and execution resumes at the code just after the call to the function.
When a function is entered, the stack pointer is decreased to allocate more space on the stack for local (automatic) variables. If the function has one local 32 bit variable four bytes are set aside on the stack. When the function returns, the stack pointer is moved back to free the allocated area.
If a function has parameters, these are pushed onto the stack before the call to the function. The code in the function is then able to navigate up the stack from the current stack pointer to locate these values.
Nesting function calls work like a charm. Each new call will allocate function parameters, the return address and space for local variables and these activation records can be stacked for nested calls and will unwind in the correct way when the functions return.
As the stack is a limited block of memory, you can cause a stack overflow by calling too many nested functions and/or allocating too much space for local variables. Often the memory area used for the stack is set up in such a way that writing below the bottom (the lowest address) of the stack will trigger a trap or exception in the CPU. This exceptional condition can then be caught by the runtime and converted into some kind of stack overflow exception.
The heap contains a linked list of used and free blocks. New allocations on the heap (by new or malloc) are satisfied by creating a suitable block from one of the free blocks. This requires updating list of blocks on the heap. This meta information about the blocks on the heap is also stored on the heap often in a small area just in front of every block.
As the heap grows new blocks are often allocated from lower addresses towards higher addresses. Thus you can think of the heap as a heap of memory blocks that grows in size as memory is allocated. If the heap is too small for an allocation the size can often be increased by acquiring more memory from the underlying operating system.
Allocating and deallocating many small blocks may leave the heap in a state where there are a lot of small free blocks interspersed between the used blocks. A request to allocate a large block may fail because none of the free blocks are large enough to satisfy the allocation request even though the combined size of the free blocks may be large enough. This is called heap fragmentation.
When a used block that is adjacent to a free block is deallocated the new free block may be merged with the adjacent free block to create a larger free block effectively reducing the fragmentation of the heap.
- Stored in computer RAM just like the heap.
- Variables created on the stack will go out of scope and are automatically deallocated.
- Much faster to allocate in comparison to variables on the heap.
- Implemented with an actual stack data structure.
- Stores local data, return addresses, used for parameter passing.
- Can have a stack overflow when too much of the stack is used (mostly from infinite or too deep recursion, very large allocations).
- Data created on the stack can be used without pointers.
- You would use the stack if you know exactly how much data you need to allocate before compile time and it is not too big.
- Usually has a maximum size already determined when your program starts.
- Stored in computer RAM just like the stack.
- In C++, variables on the heap must be destroyed manually and never fall out of scope. The data is freed with delete, delete, or free.
- Slower to allocate in comparison to variables on the stack.
- Used on demand to allocate a block of data for use by the program.
- Can have fragmentation when there are a lot of allocations and deallocations.
- In C++ or C, data created on the heap will be pointed to by pointers and allocated with new or malloc respectively.
- Can have allocation failures if too big of a buffer is requested to be allocated.
- You would use the heap if you don't know exactly how much data you will need at run time or if you need to allocate a lot of data.
- Responsible for memory leaks.
readers, This Tutorial Ends Here.
I Hope You Enjoyed It