Реализация GNU libc alloca()
читает:
# define alloca(size) __builtin_alloca (size)
Он использует встроенный компилятор, поэтому он полностью зависит от того, как он реализован компилятором. В частности, это зависит от того, как обрабатывается стек, который является структурой данных, зависящей от машины и ABI.
Рассмотрим конкретный случай. На моей машине это сборка для alloca(100000000000L)
:
0e9b: movabsq $-100000000016, %rax ; * Loads (size + 16) into rax.
0ea5: addq %rax, %rsp ; * Adds it to the top of the stack.
0ea8: movq %rsp, -48(%rbp) ; * Temporarily stores it.
0eac: movq -48(%rbp), %rax ; * These five instructions round the
0eb0: addq $15, %rax ; value stored to the next multiple
0eb4: shrq $4, %rax ; of 0x10 by doing:
0eb8: shlq $4, %rax ; rax = ((rax+15) >> 4) << 4
0ebc: movq %rax, -48(%rbp) ; and storing it again in the stack.
0ec0: movq -48(%rbp), %rax ; * Reads the rounded value and copies
0ec4: movq %rax, -24(%rbp) ; it on the previous stack position.
Скомпилировано с использованием gcc-4.2 -g test.c -o test
из следующей программы:
Теперь, когда есть на что ссылаться, можно ответить на ваши вопросы:
Выделяет ли он столько байтов, сколько может, пока стек не встретится с сегментом кучи?
Он просто слепо увеличивает стек на запрошенное количество байтов. Проверка границ вообще не выполняется, поэтому и указатель стека, и возвращаемое значение теперь, вероятно, будут находиться в недопустимом месте. Попытка чтения/записи из возвращаемого значения (или помещения в стек) приведет к ошибке SIGSEGV
.
Что он возвращает, указатель на первый байт после вершины стека перед вызовом main?
Он возвращает указатель на первый байт выделенной памяти.
После возврата alloca()
указатель стека отличается от того, что был до вызова alloca()
?
Да, см. объяснение выше. Кроме того, когда функция, вызвавшая alloca
, вернется, стек будет восстановлен до предыдущего кадра, и его снова можно будет использовать.
person
MBlanc
schedule
12.03.2014