Memory can be accessed by the CPU, and must be accessed in contiguous, power of two size chunks of bytes.
The memory of a computer is usually split up into 4 main sections.
The code segment contains the compiled machine instructions and is read only to ensure you can't accidentally overwrite your code at runtime.
The data segment contains any global and static variables.
The stack stores local variables, function parameters, and return addresses. The stack typically grows downward towards lower addresses in memory and is automatically managed, (ie. the addresses are freed when functions return).
The heap is used for dynamically allocated memory (ie. malloc in C and new in C++). The heap typically grows upwards towards higher addresses in memory and is manually managed, (ie. you must free the memory when you're done with it).
When a program accesses memory that has already been freed, the contents at that location are undefined because the system may have reallocated that memory for other purposes. Pointers pointing to this freed memory are called dangling pointers.
int *i = new int;
*i = 5;
delete i;
cout << *i << endl;
Here, i points to memory that has been deallocated. Accessing or writing to it can produce unexpected results.
To prevent using freed memory, you can set the pointer to NULL after deletion. This way, dereferencing it will trigger a crash (e.g., segmentation fault), making the bug easier to detect:
int *i = new int;
*i = 5;
delete i;
i = NULL;
cout << *i << endl; // Seg fault
When a program loses access to allocated space before it has been freed (ie. by reassigning a pointer), the space can no loner be referenced, or freed. This memory therefore remains marked as allocated for the lifetime of the program. Typically memory leaks occur with memory on the heap.
int *i = new int;
int b = 2
*i = 5;
i = &b;
The original address of
iwas lost and can no longer be freed causing a memory leak