Почему нельзя использовать alloca в списке аргументов функции?
Цитируя второй абзац BUGS
раздел, с manpage из alloca(3)
На многих системах
alloca()
не может использоваться внутри списка аргументов вызова функции, потому что пространство стека зарезервированоalloca()
появится в стеке в середине пространства для аргументов функции.
Я не видел, как это произойдет. Взяв следующий код в качестве примера:
void f(int a, void * b, int c);
int
main(void)
{
f(1, alloca(100), 2);
}
Исходя из моего понимания, alloca
расширяет кадр стека для main
на 100 байт (путем изменения регистра указателя стека), затем указатель на этот блок памяти стека (вместе с 2 int
s) передается в кадре стека для f
, Таким образом, выделенное пространство не должно быть в середине a
, b
или же c
на самом деле это должно быть в другом кадре (который находится на кадре для main
в этом случае).
Так в чем здесь недоразумение?
1 ответ
Во-первых, сразу отметим, что alloca
не является стандартным Это расширение для платформ, которые хотели дать программистам еще больше возможностей повеситься, потенциально потребляя динамическое автоматическое пространство переменных в интересах скорости по сравнению с медленными динамическими распределителями памяти, основанными на других методах (кучах и т. Д.). (да, мое мнение, но внутри много правды).
Тем не менее, рассмотрим это:
Вы когда-нибудь писали компилятор раньше? Нет стандартной гарантии порядка вычисления аргументов функции. Поэтому предположим, что какая-то платформа решила создать запись активации для вызова f
в конечном итоге, вставив в стек активации справа налево (их выбор):
- Вставляет 2 в пространство стека записи активации.
- Выступает
alloca(100)
, который сосет тот же стек, содержащий запись активации вызова, создаваемую дополнительными 100char
, - Толкает результат (2), а
void*
в пространство стека записей активации. - Вставляет 1 в пространство стека записи активации.
- Запускает
call f
который выдвигает обратный адрес вmain
в пространство стека записи активации.
Теперь думайте о себе как о функции f
, Где вы ожидаете найти третий параметр вашей функции? Эм....
Это только один пример того, как можно бросить alloca
место где-то, что может вызвать проблемы.