user3366894
user3366894

Reputation: 9

Deleting an array of pointers without a specified size

I can't figure out why the following C++ code compiled in VS2013 results in a crash.

#include "stdafx.h"

class A {};

void main()
{
    A** arr1 = new A*[5] { new A(), new A(), new A(), new A(), new A() };
    delete[] arr1;
    A** arr2 = new A*[] { new A(), new A(), new A(), new A(), new A() };
    delete[] arr2;
}

The first array gets initialized and deleted correctly, but the second results in a "%Filename%.exe has triggered a breakpoint" exception on the delete[] arr2 line followed by a debug assertion:

File: f:\dd\vctools\crt\crtw32\misc\dbgheap.c
Line: 1322

Expression: _CrtIsValidHeapPointer(pUserData)

The difference between these two arrays is quite obvious: one has an explicitly specified length, the other doesn't. But isn't the compiler supposed to be clever enough to determine the length from the number of items in the following initializer list? Because it does that just fine if the array consists of raw objects (i.e. A* arr = new A[] { A(), A(), A() }).

Please point me to what I'm doing wrong or explain the reason behind this.

Disregard the memory leaks from the array items. They get deleted in the real program, this one was quickly thrown together for a demonstration. The crash occurs either way.

Upvotes: 0

Views: 464

Answers (2)

user2460683
user2460683

Reputation:

g++ 2.8.1 won't compile arr2:

foo8.cpp: In function ‘int main()’:
foo8.cpp:7:23: error: expected primary-expression before ‘]’ token
     A** arr2 = new A*[] { new A(), new A(), new A(), new A(), new A() };
                   ^
foo8.cpp:7:71: error: too many initializers for ‘A* [1]’
     A** arr2 = new A*[] { new A(), new A(), new A(), new A(), new A() };

Taken with what @CantChooseUsernames found, I guess there is something subtle about c++11 I'm missing, I don't understand why that (in terms of the initializer list) is a different case from:

A arr3[] {A(),A(),A()};

which compiles just fine.

Upvotes: 0

Brandon
Brandon

Reputation: 23500

To see what's really going on, I tried overloading the new and delete operators. I tried overloading new[] and delete[] however VS2013 says it's already defined in some .lib file.. so the following will have to do.. (Mind you I have never overloaded new or delete before so I hope this is right)

This is a 32 bit program where sizeof(int) = 4.

#include "stdafx.h"
#include <iostream>

void* operator new(std::size_t size) //this is called..
{
    std::cout << "Allocated: "<<size<<"\n";
    return malloc(size);
}

void operator delete(void* ptr) //this function never gets called.
{
    std::cout << "DeAllocated\n";
    free(ptr);
}

int main()
{
    int** arr1 = new int*[2] {new int(1), new int(2)};
    delete[] arr1;

    std::cout << "\n\n";

    int** arr2 = new int*[] {new int(3), new int(4)};
    delete[] arr2;
}

The results are:

Allocated: 8
Allocated: 4
Allocated: 4


Allocated: 0
Allocated: 4
Allocated: 4

So where does that 8 come from? Hmm?

Let's change the first example to:

int** arr1 = new int*[3] {new int(1), new int(2), new int(3)};

and the second to:

int** arr2 = new int*[] {new int(4), new int(5), new int(6)};

The results are now:

Allocated: 12
Allocated: 4
Allocated: 4
Allocated: 4


Allocated: 0
Allocated: 4
Allocated: 4
Allocated: 4

Do you see what is happening now? The second seems to be allocating the wrong size. In other words, I think it says that arr2 is of size 0 whereas arr1 is of size 12.. Just a guess at what my results say lol.

Upvotes: 1

Related Questions