Одна ошибка с alloca
состоит в том, что longjmp
перематывает его.
То есть, если вы сохраните контекст с помощью setjmp
, затем alloca
некоторой памяти, а затем longjmp
в контексте, вы можете потерять alloca
память (без какого-либо уведомления). Указатель стека возвращается туда, где он был, и поэтому память больше не резервируется; если вы вызываете функцию или делаете другую alloca
, вы закроете исходную alloca
.
Чтобы уточнить, что я здесь конкретно имею в виду, это ситуация, при которой longjmp
не возвращается из функции, где имел место alloca
! Скорее функция сохраняет контекст с setjmp
; затем выделяет память с помощью alloca
и, наконец, в этом контексте выполняется longjmp. Память alloca
этой функции не полностью освобождена; просто вся память, которую он выделил, начиная с setjmp
. Конечно, я говорю о наблюдаемом поведении; ни одно из alloca
, которые я знаю, не задокументировано
Обычно в документации основное внимание уделяется концепции, согласно которой alloca
память связана с активацией функции , а не с каким-либо блоком; что множественные вызовы alloca
просто захватывают больше стековой памяти, которая освобождается после завершения функции. Не так; память фактически связана с контекстом процедуры. Когда контекст восстанавливается с помощью longjmp
, то же происходит и с предыдущим alloca
состоянием. Это является следствием того, что сам регистр указателя стека используется для распределения, а также (обязательно) сохраняется и восстанавливается в jmp_buf
.
Между прочим, это, если оно работает таким образом, обеспечивает вероятный механизм для преднамеренного освобождения памяти, которая была выделена с помощью alloca
.
Я столкнулся с этим как основной причиной ошибки.