Nathan Ridley
Nathan Ridley

Reputation: 34406

C++ - safety of allocating memory for an array, then returning a pointer to be deleted externally

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

Answers (5)

Jovibor
Jovibor

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

ChrisD
ChrisD

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

Miroslav Franc
Miroslav Franc

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

Steephen
Steephen

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

Anthony Calandra
Anthony Calandra

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

Related Questions