Какими техническими недостатками обладают VLA в стиле C99?

Я слышал от многих людей, что массив переменной длины, представленный в C99, ужасен. Некоторые ребята из IRC минуту назад сказали: «Я не думаю, что C ++ получит VLA, strousoup сделал несколько очень негативных комментариев о них».

Каковы причины, почему эти люди ненавидят VLA?

10

Решение

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

Предстоящая версия стандарта кодирования MISRA-C, скорее всего, также запретит VLA.

7

Другие решения

Хотя у массивов переменной длины есть свои проблемы, следует помнить, как они возникли: в качестве замены alloca(), что возможно четное Больше проблематичный.

Хотя это было тривиально для реализации на PDP-11, это было не так на других архитектурах и Ричи и Томпсона удалил его из своей реализации.

Тем не менее, автоматическое распределение переменных размеров было достаточно полезным, чтобы alloca() был воскрешен, несмотря на свои проблемы (в частности, он не может использоваться везде, где возможны произвольные вызовы функций, и на многих архитектурах он должен быть встроен в компилятор в любом случае). Рабочая группа C согласилась с предоставлением такой функции, но считала, что переменная длина представляет собой превосходное решение.

Если вы посмотрите на функции, добавленные с C99 (комплексные числа, математика общего типа, restrict, …), вы должны заметить, что многие из них направлены на то, чтобы сделать C лучшим языком для числовых вычислений. Там также полезны массивы переменной длины, и я думаю, что Фортран уже имел их в то время. Кроме того, их введение также привело к изменению модифицированных производных типов (например, указателей на массивы переменного размера), которые особенно полезны при работе с матрицами.

6

Как уже отмечали другие, VLA позволяет очень легко переполнять ваш стековый фрейм. Я не пишу компилятор, но, насколько я понимаю, VLA также может быть средством поддержки (теперь они не обязательны в C2011). И их использование ограничено областью блока или функции; вы не можете использовать VLA в области видимости файла, и они не могут иметь внешнюю связь.

Я не хотел бы, чтобы синтаксис VLA исчез, хотя; это очень удобно, когда динамично выделение многомерных массивов, где внутренние измерения не известны до времени выполнения, например:

size_t r, c;
// get values for r and c
int (*arr)[c] = malloc(r * sizeof *arr);
if (arr)
{
...
arr[i][j] = ...;
...
free(arr);
}

Одно смежное распределение (и одно соответствующее free), а также Я могу подписать его как 2D-массив. Альтернативы обычно подразумевают частичное распределение:

size_t r, c;
...
int **arr = malloc(sizeof *arr * r);
if (arr)
{
for (i = 0; i < c; i++)
arr[i] = malloc(sizeof *arr[i] * c);
...
arr[i][j] = ...;
...
for (i = 0; i < c; i++)
free(arr[i]);
free(arr);
}

или с использованием 1-го смещения:

int *arr = malloc(sizeof *arr * r * c);
if (arr)
{
...
arr[i * r + j] = ...;
...
free(arr);
}
4

VLA значительно облегчают переполнение стека. В большинстве мест, где вы будете использовать VLA, вы будете основывать длину на одном из параметров функции. Если параметр является чем-то, чего вы не ожидаете, вы можете выделить очень большой массив в стеке. Если вы не уверены, что никакая комбинация аргументов не может привести к переполнению стека, вам следует использовать динамическое распределение.

Единственное место, где их использование может иметь смысл, это встроенные платформы, поскольку при выполнении встроенного программирования одна из немногих ситуаций, когда вы, вероятно, будете достаточно внимательно следить за использованием вашей памяти, чтобы быть уверенным, что у вас не будет переполнения стека ,

2
По вопросам рекламы [email protected]