Да, но это зависит от реализации alloca (). Разумная и простая реализация alloca () заключается в том, что вновь выделенный блок помещается в верх стека путем настройки указателя стека. Поэтому, чтобы освободить эту память, нам нужно только сделать отрицательное распределение (но вам нужно изучить реальную реализацию alloca ()), давайте проверим это, взяв следующую непереносимую код например:
#include <stdio.h>
#include <alloca.h>
int main()
{
unsigned long p0, p1, p2;
p0=(unsigned long)alloca(0);
p1=(unsigned long)alloca((size_t) 0x1000);
p2=(unsigned long)alloca((size_t)-0x1000);
printf( "p0=%lX, p1=%lX, p2=%lX\n", p0, p1, p2 );
return 0;
}
На старой машине x64 с clang 2.9 пример вывода:
p0=7FFF2C75B89F, p1=7FFF2C75A89F, p2=7FFF2C75B89F
Итак, мы знаем, что реализация не проверяет аргумент -0x1000, в противном случае значение без знака будет очень большим целым числом. Первоначально указатель стека был 0x ... B89F; поскольку этот стек увеличивается в сторону увеличения (0x1000), поэтому измените указатель стека up на (0x ... B89F - 0x1000) = 0x ... A89F. После отрицательного распределения (0xA89F - (-0x1000)) указатель стека вернулся к 0x ... B89F.
Однако, с gcc 4.8.3, пример вывода:
p0=7FFFA3E27A90, p1=7FFFA3E26A80, p2=7FFFA3E27A70
В /usr/include/alloca.h мы нашли:
#ifdef __GNUC__
# define alloca(size) __builtin_alloca (size)
#endif /* GCC. */
Итак, мы знаем, что встроенная функция alloca, предоставляемая gcc 4.8.3, сделала то же самое, за исключением того, что она выделяла дополнительные 0x10 байтов в качестве запаса прочности. При выполнении отрицательного распределения все равно предполагается, что оно растет вверх и поэтому пытается зарезервировать 0x10 дополнительных байтов (- 0x10), поэтому p2 = 0x ... 6A80 - (-0x1000) - 0x10 = 0x ... 7A70. Так что будьте особенно осторожны.