Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 466
Nathan Ridley Avatar asked Mar 16 '23 23:03

Nathan Ridley


1 Answers

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.

like image 176
Miroslav Franc Avatar answered Apr 09 '23 00:04

Miroslav Franc