Reputation: 34406
I'm learning C++ at the moment and there's something I'm unclear on.
If I create a function that allocates memory for an array of some type and then returns the newly-created pointer, given that the pointer is just a memory address, will a corresponding delete
statement clean up all of the allocated memory correctly, or will only the first element be deallocated, creating a memory leak with the remainder of the array? If it is cleaned up correctly, how does C++ know what to deallocate, given my presumed loss of context inherent in the return type?
int* AllocateSomething()
{
int *arr = new int[100];
// fill the array with something...
return arr;
}
int main()
{
int* p = AllocateSomething();
delete p; // what will this do?
delete[] p; // how would this know how much memory to delete?
}
Normally I would just write some test code to figure out the answer to something but given that accessing unallocated memory results in undefined behaviour, I'm not exactly sure what I would test for.
Upvotes: 4
Views: 574
Reputation: 789
If it is cleaned up correctly, how does C++ know what to deallocate
How does delete[] "know" the size of the operand array?
When you allocate memory on the heap, your allocator will keep track of how much memory you have allocated. This is usually stored in a "head" segment just before the memory that you get allocated. That way when it's time to free the memory, the de-allocator knows exactly how much memory to free.
Upvotes: 1
Reputation: 674
When you create an array on the heap using new, you are returning a pointer to the first element in the array. So in your example, when you write delete p, you are saying delete the first element in the array. However, when you say delete [] p, you are saying delete the whole thing.
Upvotes: 1
Reputation: 1352
You must
use delete[] p
the other one leads to undefined behaviour. Typically the compiler stores some number before the array to know how big it is. Depends on the implementation. Also main should return int, but that is not that serious.
EDIT: since you are interested about possible implementation here's the dissasembly (gcc 4.8, linux x86_64):
(gdb) l AllocateSomething
1 int* AllocateSomething()
2 {
3 int *arr1 = new int[100];
4 int *arr2 = new int[200];
5 int *arr3 = new int[300];
6 int *arr4 = new int[400];
7 arr1[0] = arr2[0] = arr3[0] = arr4[0] = ~0;
8
9
10
(gdb) x/20 arr1-8
0x601ff0: 0 0 0 0
0x602000: 0 0 417 0
0x602010: -1 0 0 0
0x602020: 0 0 0 0
0x602030: 0 0 0 0
(gdb) x/20 arr2-8
0x602190: 0 0 0 0
0x6021a0: 0 0 817 0
0x6021b0: -1 0 0 0
0x6021c0: 0 0 0 0
0x6021d0: 0 0 0 0
(gdb) x/20 arr3-8
0x6024c0: 0 0 0 0
0x6024d0: 0 0 1217 0
0x6024e0: -1 0 0 0
0x6024f0: 0 0 0 0
0x602500: 0 0 0 0
(gdb) x/20 arr4-8
0x602980: 0 0 0 0
0x602990: 0 0 1617 0
0x6029a0: -1 0 0 0
0x6029b0: 0 0 0 0
0x6029c0: 0 0 0 0
Memory dumps for each array. -1 marks start of the array. I'm printing from 8th element (4 bytes ints) before the start. You can clearly see the size of the array (sizeof (int) * the constant) + 17 auxiliary bytes stored in a word (8 bytes) before the array.
Upvotes: 3
Reputation: 15824
delete p; This is wrong since you allocated an array with new operator.-> first
delete[] p; This is right. -> second
When you run a C++ program there are two types of memory, one is stack memory and another is heap memory. When you use operator new system allocating memory in heap of the memory and this memory allocation is keeping in context of execution process so it is called dynamically allocated memory. Context info is not keeping in function but process wise, since it is a resource. So even after return from function, process knows its resources in hand so by using delete[] operator system can clean up allocated memory. The first pointer of your array may offset with array size depends on implementation and that will play in time of deletion of memory in case of arrays.
Upvotes: 1
Reputation: 1528
Whenever you are dynamically allocating arrays on the heap using 'new' (such as int[], bool[], etc.) you want to delete memory using delete[], otherwise as pointed out in Miroslav's answer, you will get undefined behaviour using just the 'delete' form of the operator.
If you are using C++11 or later I invite you to check out the new smart pointer features of the language such as std::unique_ptr which deals with freeing memory for you (esentially RAII).
Upvotes: 1