0

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.

3
  • In both cases, don't you have to loop through the array and delete each index and then delete[] the array pointer itself.. -- Sorry did not see disregard the memory leaks. Weird, the second declaration of the array doesn't compile for me in Mingw 4.8.1. Commented Feb 28, 2014 at 23:46
  • VS2013 compiles it just fine. VS2008, on the other hand, refuses to compile both array initialization lines. Could it be that this issue appeared as a result of added C++11 support in VS2013? Commented Feb 28, 2014 at 23:55
  • 1
    I wonder if new A*[] is even legal... Commented Mar 1, 2014 at 0:43

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

4 Comments

So [] is being treated as [0]... Which is pretty strange in my opinion. But why would A* arr = new A[] { A(), A(), A(), A(), A() }; delete[] arr; (which still outputs Allocated: 0, by the way) be deleted without any problems?
It does not work for that. int* arr = new int[]{1, 2, 3, 4, 5}; and delete[] arr; crashes the same way in VS2013.. Well for me at least. Even without overloading new and delete it crashes. :S Something about Heap Corruption and writing to the end of array of size 0. Again this also compiles in VS2013 but not gcc/g++/mingw 4.8.1
Indeed, it does crashes with int, but doesn't crash with my class A { }; or even class A { int value; } (just to rule out the possibility that the issue is because of an empty class).
You are indeed right.. I used std::cout<<"Constructed A\n"; in A's constructor.. It works and I have no clue why.
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.