Я изменил вашу программу, чтобы вычислить оценку размера стека, а затем с помощью siglongjmp возвратился из обработчика сигнала в предположительно безопасное место в main
непосредственно перед l oop, которое выделяет массив переменной длины. (Обратите внимание, что способ размещения массивов переменной длины зависит от компилятора, и не может быть безопасного способа возобновить выполнение в main
после переполнения стека).
printf с в обработчике сигналов только для отладки; их можно удалить, не затрагивая остальную часть программы.
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <signal.h>
#include <setjmp.h>
ptrdiff_t s_size_computed;
void *s_base_estimated;
sigjmp_buf env;
void handler (int signo, siginfo_t *info, void *ucontext)
{
printf("Caught signal %d\n", signo);
if (signo == SIGSEGV)
{
printf("faulting address %p\n", info->si_addr);
s_size_computed = (char *)s_base_estimated - (char *)info->si_addr;
siglongjmp(env, 1);
}
}
int main()
{
int counter = 8964;
stack_t sigstack;
sigstack.ss_sp = malloc(SIGSTKSZ);
if (sigstack.ss_sp == NULL)
{
printf("Err: malloc error\n");
exit(EXIT_FAILURE);
}
sigstack.ss_size = SIGSTKSZ;
sigstack.ss_flags = 0;
if (sigaltstack(&sigstack, NULL) == -1)
{
printf("Err: sigaltstack error\n");
exit(EXIT_FAILURE);
}
s_base_estimated = &counter;
printf("&locals %p\n", s_base_estimated);
struct sigaction act;
act.sa_flags = SA_ONSTACK|SA_SIGINFO;
sigemptyset(&act.sa_mask);
act.sa_sigaction = handler;
sigaction(SIGSEGV, &act, NULL);
if (sigsetjmp(env, 0) == 1)
{
printf("computed stack size %td\n", s_size_computed);
exit(1);
}
do
{
char a[counter];
counter += 8964;
a[0] = 0; /* access element closest to top of stack (x86) */
} while (1);
return 0;
}
Вот вывод на моей системе Ubuntu:
mp:~$ ./stack
&locals 0x7fffeb60e0dc
Caught signal 11
faulting address 0x7fffeae0d960
computed stack size 8390524
mp:~$ ulimit -s
8192