Как создаются инструкции массива переменной длины? - PullRequest
2 голосов
/ 21 апреля 2020

Массивы переменной длины поддерживаются в C:

int main(){
   int num = 5;
    int arr[num];
    return 0;
}

Я понимаю, что arr выделяется во время выполнения. Как это достигается? Вызывает ли она C исполняющую функцию для распределения байтов? Поскольку объем выделения не известен во время компиляции, следовательно, не должно существовать инструкций для выделения стека.

В качестве дополнительного вопроса, является ли хорошей практикой использование их сверх malloc и выделение кучи, поскольку VLA официально не являются поддерживается в C ++?

Редактировать:

Похоже, что это может быть реализовано с использованием alloca, который размещается в кадре стека.

Ответы [ 3 ]

3 голосов
/ 21 апреля 2020

Как выполняется распределение VLA, зависит от индивидуальной реализации - те, с которыми я знаком, выделяют из стека, но не обязаны.

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

Однако с 2011 года поддержка VLA необязательна , поэтому я бы не стал слишком сильно на них полагаться.

0 голосов
/ 22 апреля 2020

В качестве дополнительного вопроса, рекомендуется ли использовать их вместо mallo c и выделения кучи,

Нет, рассмотрите вместо этого использование гибких элементов массива как последний член ваших struct -s переменного размера. Убедитесь, что mallo c не завершился с ошибкой во время выполнения.

Во встроенном программировании VLA полезны, когда вы можете гарантировать, что они достаточно малы, так как вы не хотите взрывать до стека вызовов . Минимуму предшествует int arr[num]; с чем-то вроде assert(num>0 && num<100); или еще лучше, добавьте такую ​​проверку во время выполнения. Вы можете использовать такие инструменты, как Frama- C, чтобы доказать это статически.

0 голосов
/ 21 апреля 2020

Не только, как вы правильно сказали

VLA официально не поддерживаются в C ++.

, но они также были переведены в "опциональную функцию" начиная с C11 (хотя они были добавлены только в C99!). Это на самом деле причина не использовать их, чтобы иметь переносимый код.


Детали его выделения памяти, к сожалению, зависят от реализации . Они обычно распределяются в стеке большинством компиляторов как автоматические c переменные хранения (согласно моему исследованию и моему личному опыту), но также могут быть размещены в куче.

Распределение массивов в стеке может привести к проблемам переполнения стека, особенно во встроенной среде. Я предлагаю посетить этот вопрос (о том, что VLA не поддерживается в стандартах C ++); в частности, действительно интересно этот ответ , @Quuxplusone (enphasis is my):

Массивы переменной длины в C99 были в основном ошибкой. Чтобы поддерживать VLA, C99 пришлось пойти на [...] уступки здравому смыслу.

Менее важно в мире C ++, но чрезвычайно важно для целевой аудитории C встраиваемых систем. -системным программистам объявлять VLA означает разбивать произвольно большой кусок вашего стека. Это гарантированное переполнение стека и cra sh. (Каждый раз, когда вы объявляете int A[n], вы неявно утверждаете, что у вас есть 2 ГБ стека для резервирования. В конце концов, если вы знаете, что n определенно меньше чем 1000 здесь ", тогда вы просто объявите int A[1000].


Насколько я вижу, их главное преимущество - наличие массивов переменной длины с local scope , чего нельзя достичь с помощью его альтернатив:

/* Fixed length array, either global or local */
int arr[100];

/* Dynamic allocation */
int * arr = malloc (100 * sizeof (int));

В большинстве случаев, в любом случае, разработчик либо

  • знает, какой максимальный размер может иметь VLA. Так почему бы не выделить его статически с фиксированной длиной?
  • Не контролирует максимальный размер, поэтому им придется выполнять проверку работоспособности, чтобы избежать переполнения стека. Так почему бы не ограничить его размер с помощью фиксированной длины? ?
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...