Если мы посмотрим на примечания к выпуску gcc 4.9, похоже, что они добавили поддержка инициализации VLA с ожиданием, что VLA будет поддерживаться в будущей версии C++:
G++ поддерживает массивы переменной длины C++1y. G++ уже давно поддерживает VLA в стиле GNU/C99, но теперь дополнительно поддерживает инициализаторы и захват лямбда-выражений по ссылке. В режиме C++1y G++ будет жаловаться на использование VLA, которое не разрешено проектом стандарта, например, на формирование указателя на тип VLA или применение sizeof к переменной VLA. Обратите внимание, что теперь кажется, что VLA не будут частью C++14, а станут частью отдельного документа, а затем, возможно, C++17.
Мы видим, что до версии 4.9 мы не можем инициализировать VLA.
error: variable-sized object 'opt' may not be initialized
int opt[rows][cols] = {0};
^
но в 4.9.1 и после он перестает жаловаться, и у него нет той ошибки, которую мы видим в более последние версии.
Так что это похоже на регресс.
Обратите внимание, что clang отказывается разрешить инициализацию VLA (которую они поддерживают как расширение). см. живой пример. Что имеет смысл, поскольку C99 не разрешает инициализацию VLA :
Тип объекта, который нужно инициализировать, должен быть массивом неизвестного размера или типом объекта, который не является типом массива переменной длины.
Ошибка gcc 69517
gcc отчет об ошибке: SEGV на VLA с избыточными элементами инициализатора имеет комментарий, который дает некоторые сведения об этой функции:
(В ответ Якубу Елинеку из комментария №16)
Ошибка здесь в том, что G++ принимает инициализатор VLA с большим количеством элементов, чем есть место в VLA, а затем уничтожает стек во время выполнения дополнительными элементами. Это регрессия по сравнению с GCC 4.9.3, которая реализует C++ VLA, как указано в n3639 (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3639)..html). Это задокументировано в изменениях GCC 4.9 (https://gcc.gnu.org/gcc-4.9/changes.html), в котором эта функция выделена на следующем примере:
void f(int n) {
int a[n] = { 1, 2, 3 }; // throws std::bad_array_length if n < 3
...
Впоследствии VLA были удалены из C++, а также частично (но не полностью) удалены из G++, что приводит к тому, что программы C++, разработанные и протестированные с помощью G++ 4.9, ломаются при переносе на более позднюю версию.
C++ VLA будет безопаснее использовать с патчем, упомянутым в комментарии №9. Этот патч пришлось вернуть из GCC 6.0, потому что он вызывал проблемы в Java. Java был удален, и я планирую/надеюсь повторно представить патч для GCC 8. (Я хотел сделать это для GCC 7, но не смог.)
person
Shafik Yaghmour
schedule
31.08.2018
int opt[rows][cols]
недопустимо для C++ - размеры массивов должны быть константами времени компиляции, а не переменными. - person   schedule 31.08.2018rows
иcolumns
наconst
, проблема будет устранена. - person imreal   schedule 31.08.2018error: variable-sized object may not be initialized
. - person   schedule 31.08.2018calloc
обнуляет память. Функцияmalloc
не изменяет память; вы получаете то, что получаете. - person Thomas Matthews   schedule 01.09.2018