Удаление массива указателей без указанного размера

0

Я не могу понять, почему следующий код C++, скомпилированный в VS2013, приводит к сбою.

#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;
}

Первый массив инициализируется и удаляется правильно, но второй результат: "% Filename%.exe вызвало исключение точки останова" в строке delete[] arr2 за которой следует утверждение отладки:

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

Expression: _CrtIsValidHeapPointer(pUserData)

Разница между этими двумя массивами довольно очевидна: у одного есть явно заданная длина, другая - нет. Но разве компилятор не должен быть достаточно умным, чтобы определить длину из числа элементов в следующем списке инициализаторов? Потому что он делает это просто отлично, если массив состоит из необработанных объектов (то есть A* arr = new A[] { A(), A(), A() }).

Пожалуйста, укажите мне, что я делаю неправильно или объясню причину этого.

Не учитывайте утечки памяти из элементов массива. Они удаляются в реальной программе, и эта была быстро брошена вместе для демонстрации. Авария происходит в любом случае.

  • 0
    В обоих случаях вам не нужно перебирать массив и delete каждый индекс, а затем delete[] сам указатель массива. - Извините, не видел disregard the memory leaks . Странно, второе объявление массива не компилируется для меня в Mingw 4.8.1.
  • 0
    VS2013 компилирует это просто отлично. VS2008, с другой стороны, отказывается компилировать обе строки инициализации массива. Может ли быть так, что эта проблема появилась в результате дополнительной поддержки C ++ 11 в VS2013?
Показать ещё 1 комментарий
Теги:
arrays
pointers
delete-operator

2 ответа

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

Итак, откуда это взялось? Хм?

Пусть первый пример изменится на:

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.. Просто догадайтесь, что мои результаты говорят lol.

  • 0
    Так что [] рассматривается как [0] ... Что довольно странно, на мой взгляд. Но почему A* arr = new A[] { A(), A(), A(), A(), A() }; delete[] arr; (который по-прежнему выводит Allocated: 0 , кстати) удалить без проблем?
  • 0
    Это не работает для этого. int* arr = new int[]{1, 2, 3, 4, 5}; и delete[] arr; вылетает точно так же в VS2013 .. ну для меня по крайней мере. Даже не перегружая new и delete его вылетает. : S Что-то о Heap Corruption и записи в конец массива размера 0. Опять это также компилируется в VS2013, но не в gcc / g ++ / mingw 4.8.1
Показать ещё 2 комментария
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, я думаю, что есть что-то тонкое о С++ 11, я не понимаю, почему это (в терминах списка инициализаторов) - это другой случай:

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

который компилируется просто отлично.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню