Do not properly deleted pointers fragment memory?
No. Lots of memory allocations and releases will fragment memory.
Here's an intuitive explanation of memory allocation (it is more complex than that and my example is naive at best and ignores lots of issues, but it should provide you with some idea).
Memory allocation usually happens in (at least) two steps:
The OS allocates blocks of memory for the application.
The application allocates memory from the available blocks for it's own use.
If the application uses all it's available memory (or it cannot allocate anymore), the OS will allocate more memory for the application. This is done transparently to the application, but it takes time (that's why memory allocations are slow).
When the application releases memory, the addresses/blocks are marked as free and will be reused on subsequent allocation requests (new/malloc/realloc/etc) by the application.
Memory fragmentation happens when the blocks of memory allocated to the application become fragmented (some fragments are allocated and some free).
For example:
int *a = new int;
int *b = new int;
int *c = new int;
int *d = new int;
int *e = new int;
int *f = new int;
// if the memory blocks for the pointers were allocated contiguously,
// the heap will look like this:
// [ a ][ b ][ c ][ d ][ e ][ f ][ free memory ... ]
// sometime later:
delete b;
delete d;
delete e;
// same memory block will look like this:
// [ a ][free][ c ][free][free][ f ][ free memory ... ]
For the sake of simplicity, let's say your application starts with 1000 bytes of memory available). If in a first step you allocated 200 int*
(200 different variables) you'd have 200 x 4=800 bytes allocated, 200 bytes free.
If you wanted to allocate (in a second step) new int[100]
more (one pointer, 400 more bytes), you wouldn't have enough memory available and the application would have to request more from the OS. You'd need at least 200 more bytes in your current block, or a new block of at least 400 bytes from the OS).
If you deleted memory allocated in step 1 to make space for allocating in step 2, it would be critical what memory you deleted:
If you deleted the last allocated pointers - you'd need to delete the last 50 pointers (50x4 = 200) - you'd have 200 bytes released + 200 unalocated = 400 needed). OK
If you deleted every 2nd pointer allocated at step 1 (or the first 50 pointers for that matter) you'd have 400 bytes available, but fragmented and no 400 bytes of continuous memory available. Your allocation in step 2 would fail, due to the fragmented memory.
My mistake for using a bad example. So int *a = new int[100];
never gets deleted, and even if it gets deleted, an answer says that the pointee is deleted, not the pointer. Yet pointers also have a length.
When you have int *a = new int[100];
you have here two parts:
The memory for a
(the pointer itself) is 4 bytes (assuming a 32 bit architecture) allocated on the stack.
The memory pointed to by a
is 400 bytes, allocated on the heap.
The heap memory will be released when you call delete[]a;
. The stack memory (for the pointer itself) will be released to the available stack space when a* goes out of scope.
You only need to concern yourself with deleting the heap memory. The stack memory is released/reused as necessary by the program itself.