LINUX.ORG.RU

Почему clang не может скомпилить объявление массива с размером из переменной?

 


0

4
// Не-POD тип:
struct Rect
{
    uint32_t coords[4];

    Rect()
    {
        coords[0] = coords[1] = coords[2] = coords[3] = 0;
    }
};

// ...

// Создаём на стеке массив
Rect maxrects[some_size * 2];    // fatal error <---

Ошибка компиляции через clang на строке со стрелкой:

fatal error: variable length array of non-POD element type 

gcc жрёт не возражая.

А в чём физическая проблема скомпилить сабжевый массив переменной длины? Просто подвинул смещение на стеке (регистр ESP или что там я уже не помню) на переменное число элементов и всё, массив создан. И какая ему здесь разница, POD или не POD? Ну для не-POD вызвал конструктор на каждый элемент и всё, в чём проблема?

Ну стандарт запрещает, ок, но ведь для запрета нет никаких существенных оснований - вон даже gcc решил на этот запрет болт забить. Ну варнинг бы выдали, зачем фатал еррор? Чё такого-то, ни одно животное же не страдает нигде.

НЕ НАДО пейсать фтопеге, что стандарт это запрещает. Вопрос о том, почему это есть так.

Ладно, нашёл вот чтива кусок по сабжу: http://stackoverflow.com/questions/1887097/variable-length-arrays-in-c — срач именно по вопросу о том, какого хрена это возникло в стандарте. Выглядит неубедительно всё равно: как-то непохоже на плюсовщиков, где выстрел в ногу никогда не осуждался.



Последнее исправление: hlamotron (всего исправлений: 6)

Потому что стандарт плюсов не разрешает использовать массивы переменной длины. ГЦЦ для этого использует своё расширение.

Тут ещё посоны нашептали, что вроде как в С++14 снято ограничение на длину массива как на constant-expression.

mkam
()
Последнее исправление: mkam (всего исправлений: 1)

Интереса ради добавь к гцц опцию -std=c++11.

mkam
()

Сколь помню, то это фишка gcc которая не присутствует в стандарте, потому clang все делает правильно

anonymous
()
Ответ на: комментарий от Pavval

Не вижу в VLA ничего, что бы его оправдывало.

hlamotron
() автор топика

НЕ НАДО пейсать фтопеге, что стандарт это запрещает. Вопрос о том, почему это есть так.

Вот и выросло поколение, для которого «stack overflow» — это такой сайтик в интернетах.

Gvidon ★★★★
()
Ответ на: комментарий от Gvidon

Только поэтому? Пф, варнингом бы обошлись.

Кто меня защитит от стека оверфлоу, когда у меня ресурсия окуительно длинная?

От стека-оферфлоу в плюсах ничто не спасёт, фигли стандарт ставит заплатку на одну дырочку сетчатого забора?

hlamotron
() автор топика
Ответ на: комментарий от hlamotron

Кто меня защитит от стека оверфлоу, когда у меня ресурсия окуительно длинная?

Зачем безмозглых защищать?

Pavval ★★★★★
()
Ответ на: комментарий от tailgunner

ЕМНИП, в C99 оно обязательно

Да.

и этого достаточно.

Нет.

Pavval ★★★★★
()

Почему clang не может скомпилить объявление массива с размером из переменной?

gcc жрёт не возражая

Дай угадаю, у тебя федора или арч? И gcc версии где-то 6.*?

Deleted
()
Последнее исправление: ecko (всего исправлений: 1)
Ответ на: комментарий от Deleted

ниугадал. gcc в крестах vla extension сто лет как поддерживает

vvviperrr ★★★★★
()

std::vector хватит всем.

anonymous
()
Ответ на: комментарий от hlamotron

Ты просто показал какой-то код, совершенно непонятно, зачем тебе нужен массив неизвестного размера именно на стеке.

Gvidon ★★★★
()
Ответ на: комментарий от Gvidon

Ты так говоришь, как будто нельзя написать int m[100500] и тоже вызвать переполнение стека. От stack overflow защиты в крестах (кроме прямых рук) нет никакой.

KivApple ★★★★★
()
Ответ на: комментарий от Gvidon

Ну чисто теоретически такой массив должен создаться быстрее, чем массив в куче.

KivApple ★★★★★
()
Ответ на: комментарий от KivApple

Если программист пишет int m[100500], то он ССЗБ, и его проблемы никого не волнуют. Да, я знаю про рекурсию, alloca и прочие уже существующие способы отстрелить себе ногу, но это не повод вводить новые, да ещё и с ломающим шаблон синтаксисом. sizeof, вычисляющийся во время исполнения, — это что-то за гранью добра и зла.

Gvidon ★★★★
()

для не-POD вызвал конструктор на каждый элемент и всё

А конструктор бросил исключение. И чё теперь делать?

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от Gvidon

Я точно знаю, что размер небольшой и знаю его пределы. Могу конечно объявить предельного размера, но вот решил заняться преждевременной оптимизацией и вхрячить переменную.

hlamotron
() автор топика
Ответ на: комментарий от no-such-file

Бросил исключение - ну и пусть летит себе.

hlamotron
() автор топика

Нет, тебе дали кучу — юзай кучу. Не нравится — пиши свой язык, компилятор и софт на нем.

a1batross ★★★★★
()
Ответ на: комментарий от hlamotron

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

А в чем оптимизация тогда выходит? Думаешь выделить на стеке 10 байт быстрее чем 1024?

anonymous
()
Ответ на: комментарий от a1batross

Мне помимо кучи дали стек. Непонятно, почему я не могу отожрать от него произвольное небольшое число байтов в диапазоне 1...64.

hlamotron
() автор топика
Ответ на: комментарий от anonymous

Нет, думаю что если не всегда жрать стек на полную катушку, то рекурсии хватит на поглубже ) Дебилизм конечно.

hlamotron
() автор топика

The number of elements of the array, the array bound, must be a constant expression (§10.4). If
you need variable bounds, use a vector (§4.4 .1, §31.4). For example:

void f(int n)
{
    int v1[n];         // error: array size not a constant expression
    vector<int> v2(n); // OK: vector with n int elements
}


TC++PL, 4th edition, Stroustrup.

evilface ★★
()
Ответ на: комментарий от evilface

Что издание четвёртое указано специально, ибо там всё про C++11.

evilface ★★
()

НЕ НАДО пейсать фтопеге, что стандарт это запрещает. Вопрос о том, почему это есть так.

Так вам нужен ответ или нет?

andreyu ★★★★★
()

А в чём физическая проблема скомпилить сабжевый массив переменной длины?

А где, собственно, должна эта память выделяться? Почему на стеке, а не в куче? И почему не в какой нибудь секции .data? На мой взгляд, это абсолютно unpredictable behavior. Когда переменная сonst, то компилятор знает длину массива уже на этапе компиляции, вот это уже хорошо.

Чё такого-то, ни одно животное же не страдает нигде.

Плюсы и так предоставляют исчерпывающие возможности для байтоиметельства во все стеки и кучи, а есть такие люди, которым если разрешить, они будут использовать вообще везде. Как ты докажешь студенту Национального Подзалупинского Университета Мухосранского Технического Педоинженернофилологоэкономического Института, что память надо выделять типа там оператором new, а не massiv[kalichestvo_chegototam] ?

nikolnik ★★★
()
Ответ на: комментарий от mamba_namba_karamba

А почему безмозглых можно не защищать в случае с длинной рекурсией, а в случае с VLA непременно нужно защитить?

Потому что эффекты от длинной рекурсии ловит каждый идущий к успеху джун, который учит рекурсию и как всегда ошибается в условии выхода. И начинает понимать. А VLA - притягательный, но абсолютно неочевидный идиотам рассадник уязвимостей.

Pavval ★★★★★
()
Ответ на: комментарий от nikolnik

Короче, аргумент про .data интересен, не думал об этом.

hlamotron
() автор топика
Ответ на: комментарий от Pavval

бсолютно неочевидный идиотам рассадник уязвимостей.

не более неочевидный, чем обращение по индексу к тому же массиву выделенному на куче.

mamba_namba_karamba
()

для С есть фичи С99, для плюсов придумали вектор когда еще не было С99

reprimand ★★★★★
()

А в чём физическая проблема скомпилить сабжевый массив переменной длины? Просто подвинул смещение на стеке (регистр ESP или что там я уже не помню) на переменное число элементов и всё, массив создан.

А если я три таких массива создам, как компилятор будет определять, где на стеке какой из них? Если где-то возникнет исключение, как программа будет разворачивать стек, когда неизвестно, где там что?

Это, конечно, всё можно сделать, но несколько сложнее, чем просто смещением указателя на стек. Компилятор имеет право этого не реализовывать.

proud_anon ★★★★★
()

Раз знаешь что значения не выйдут за пределы к пример 64, так и создавай массив такого размера, либо используй std::vector.

Int64 ★★★
()

Про alloca уже упоминали?

DELIRIUM ☆☆☆☆☆
()

Проверил, для C может. Ну и OK

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.