После p = новая строка [0] и p = new int [0], почему версия строки сбой при удалении [] p? - программирование
Подтвердить что ты не робот

После p = новая строка [0] и p = new int [0], почему версия строки сбой при удалении [] p?

У меня есть два блока кода около new[] и delete[]:

1)

#include <string>

int main()
{
  std::string *p = new std::string[0];
  delete[] p;

  return 0;
}

2) В этом случае я просто изменяю std::string на int

int main()
{
  int *p = new int[0];

  delete[] p;

  return 0;
}

Мой вопрос:

Почему первая программа выходит из строя со следующим сообщением (в среде linux):

Segmentation fault (core dumped)

Но вторая программа работает без ошибок?

ИЗМЕНИТЬ

компилятор: g++ (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2

Я просто использую g++ без каких-либо аргументов для его компиляции.

Если это ошибка компилятора, должны ли они произойти сбой или нет в соответствии со стандартом?

4b9b3361

Ответ 1

Это должна быть ошибка gcc. Что полное выражение new[] игнорируется, а p становится неинициализированным, а затем мы delete[] неинициализированный указатель, который сбой. Если мы скомпилируем программу с помощью -Wall, она предупредит вас, что

warning: 'p используется неинициализированным в этой функции

что явно неверно. Выражение new X[0] хорошо определено как в С++ 03, так и в С++ 11 (§5.3.4/7), и это корректно работает в clang, поэтому единственный логический вывод состоит в том, что это ошибка gcc.


Исключительная ошибка new[] существует только тогда, когда тип, который должен быть сконструирован, имеет какой-либо нетривиальный конструктор. И segfault бывает, что у типа есть деструктор, потому что delete[] тогда потребуется разыменовать неинициализированный указатель. Поэтому он падает на std::string, но не int, потому что int тривиален и std::string не является.


Это можно обойти с помощью промежуточной переменной, так что выражение не может быть напрямую оценено на 0:

size_t length = 0;
std::string* p = new std::string[length];
// ...
delete[] p;