Почему alloca нельзя использовать в списке аргументов функции?

Цитата из второго абзаца раздела BUGS со страницы руководства alloca(3)

Во многих системах alloca() нельзя использовать внутри списка аргументов вызова функции, потому что пространство стека, зарезервированное alloca(), появится в стеке в середине пространства для аргументов функции.

Мне не удалось увидеть, как это произойдет. В качестве примера возьмем следующий код:

void f(int a, void * b, int c);

int
main(void)
{
    f(1, alloca(100), 2);
}

Насколько я понимаю, alloca расширяет кадр стека для main вниз на 100 байт (путем изменения регистра указателя стека), затем указатель на этот блок памяти стека (вместе с 2 ints) передается в кадр стека для f. Таким образом, выделенное пространство не должно быть в середине a, b или c, на самом деле оно должно быть в другом кадре (который в данном случае находится в кадре для main).

Так в чем тут недоразумение?


person Naitree    schedule 29.01.2017    source источник


Ответы (1)


Во-первых, сразу обратите внимание, что alloca не является стандартным< /а>. Это расширение для платформ, которые хотели дать программистам еще больше возможностей повеситься, потенциально динамически потребляя пространство автоматических переменных в интересах скорости по сравнению с медленными распределителями динамической памяти, основанными на других методах (кучах и т. д.). (да, мое мнение, но внутри много правды).

Тем не менее, подумайте об этом:

Вы когда-нибудь писали компилятор? Не существует стандартной гарантии порядка оценки аргументов функции. Итак, просто предположим, что какая-то платформа решила создать запись активации для вызова f, в конечном итоге отправив следующую в стек активации, справа налево (на их выбор):

  1. Помещает 2 в пространство стека записи активации.
  2. Выполняет alloca(100), который засасывает тот же стек, содержащий запись активации вызова, построенную дополнительными 100 char.
  3. Помещает результат (2), void*, в пространство стека записи активации.
  4. Помещает 1 в пространство стека записи активации.
  5. Вызывает call f, который помещает адрес возврата из main в пространство стека записи активации.

Теперь представьте себя функцией f. Где вы ожидаете найти третий параметр вашей функции? Эм....

Это всего лишь один пример того, как можно где-то бросить alloca пробелов, что может вызвать проблемы.

person WhozCraig    schedule 29.01.2017
comment
third parameter указывает на 1 или 2? Почему внутри функции f мы не можем найти третий параметр? Не могли бы вы объяснить это более подробно? потому что компилятор не знает, сколько памяти, выделенной alloca, занято? - person jinbeom hong; 01.05.2021