我无法弄清楚为什么在VS2013中编译的以下C ++代码会导致崩溃。
#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;
}
第一个数组被正确初始化和删除,但第二个数组导致delete[] arr2
行上出现“%Filename%.exe已触发断点”异常,然后是调试断言:
File: f:\dd\vctools\crt\crtw32\misc\dbgheap.c
Line: 1322
Expression: _CrtIsValidHeapPointer(pUserData)
这两个数组之间的区别非常明显:一个具有明确指定的长度,另一个没有。但是,编译器是否应该足够聪明地确定以下初始化列表中项目数的长度?因为如果数组由原始对象组成(即A* arr = new A[] { A(), A(), A() }
),它就可以了。
请指出我做错了什么或解释背后的原因。
忽略数组项的内存泄漏。它们在真实程序中被删除,这一个很快就被拼凑起来进行演示。崩溃发生在任何一种方式。
答案 0 :(得分:1)
要了解实际情况,我尝试重载new
和delete
运算符。我尝试重载new[]
和delete[]
,但是VS2013说它已经在一些.lib文件中定义了..所以以下内容将要做..(请注意,我从未重载过新的或删除之前所以我希望这是对的)
这是一个32位程序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;
}
结果是:
Allocated: 8
Allocated: 4
Allocated: 4
Allocated: 0
Allocated: 4
Allocated: 4
那么8来自哪里?嗯?
让我们将第一个例子改为:
int** arr1 = new int*[3] {new int(1), new int(2), new int(3)};
和第二个:
int** arr2 = new int*[] {new int(4), new int(5), new int(6)};
结果现在是:
Allocated: 12
Allocated: 4
Allocated: 4
Allocated: 4
Allocated: 0
Allocated: 4
Allocated: 4
Allocated: 4
你看到现在发生了什么吗?第二个似乎是分配错误的大小。换句话说,我认为arr2的大小为0,而arr1的大小为12 ..只是猜测我的结果是什么意思。
答案 1 :(得分:0)
g ++ 2.8.1不会编译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() };
采用@CantChooseUsernames发现的内容,我猜有一些关于c ++ 11的微妙内容我不知道,我不明白为什么(就初始化列表而言)是一个不同的情况:
A arr3[] {A(),A(),A()};
编译得很好。