Возвращая указатель на alloca
Этот код возвращает недопустимую ссылку на переменную, расположенную в стеке? Или что:
void *f(size_t sz) {
return alloca(sz);
}
Или это особый случай, который обрабатывается реализацией / поддержкой компилятора alloca, например f(alloca(size), alloca(size))
было бы?
6 ответов
alloca
выделяет место в кадре стека f
, Вы не сможете ничего с ним сделать, когда функция вернется (она больше не "зарезервирована").
Функция alloca() распределяет байты размера пространства в кадре стека вызывающей стороны. Это временное пространство автоматически освобождается, когда функция, вызвавшая alloca(), возвращается к своему вызывающему.
Этот:
void *f() {
char* pc4 = alloca(4);
...
}
именно это:
void *f() {
char pc4[4];
...
}
Ни вы не можете вернуть / использовать pc4 вне функции во втором случае, ни вы не можете сделать то же самое в первом случае.
Да, код возвращает неверный указатель. alloca
вызов не может быть включен в функцию. Если вам нужно обернуть alloca
Вы ограничены макропакетами.
Согласно странице руководстваLinux:
alloca()
Функция выделяет место в стеке кадра вызывающей стороны и возвращает указатель на выделенный блок. Это временное пространство автоматически освобождается, когда функция, из которойalloca()
называется возврат.
Это означает, что попытка доступа к памяти, возвращенная f()
приведет к неопределенному поведению, поскольку оно освобождается, когда f()
возвращается.
Как уже говорили другие, это будет освобождено, и я не очень понимаю, как вы могли бы изменить поведение. Если вы посмотрите на то, как alloca
компилируется на amd-64:
pushq %rbp
movq %rsp, %rbp
subq $144, %rsp
movq %rsp, %rax
addq $15, %rax
shrq $4, %rax
salq $4, %rax
leave
ret
Ты видишь
1) Alloca на самом деле не является вызовом функции (потому что, как вы сказали, он должен обрабатывать стек по-другому!)
2) Что бы ни делал alloca с указателем стека, он просто будет забит в конце функции, когда rbp
перезаписывает rsp
Так вы могли бы получить поведение, о котором вы спрашиваете (без написания ассемблера)? Это сложный вопрос, и я не знаю, но похоже, что нет.
Я никогда не использовал alloca, но я читал о "встроенной проблеме" здесь: почему использование alloca() не считается хорошей практикой?
Ответ "Одна из самых запоминающихся ошибок..." очень интересный.
Поэтому неверно, что память определенно будет освобождена, когда функция выйдет из области видимости.