在 SIGSEGV 信号后打破无限循环
Break Infinite Loop After SIGSEVG Signal
我试图通过我的程序找到我的最大堆栈大小。我知道,在我的 OS 上,堆栈的最大大小约为 8MB。所以我试图进行无限循环,直到它导致分段错误。然后我需要打破这个循环,这样我才能计算大小。我怎样才能做到这一点?在 SIGSEGV 信号之后有什么办法可以打破无限循环吗?
static void handler(int signo)
{
if(signo == SIGSEGV)
{
printf("Waoh, caught signal\n");
}
}
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);
}
struct sigaction act;
act.sa_flags = SA_ONSTACK;
sigemptyset(&act.sa_mask);
act.sa_handler = handler;
sigaction(SIGSEGV, &act, NULL);
do
{
char a[counter];
counter += 8964;
} while (1);
return 0;
}
我修改了你的程序来计算堆栈大小的估计值,然后使用 siglongjmp 到 return 从信号处理程序到 main
就在分配可变长度数组的循环之前。 (请注意,可变长度数组的分配方式取决于编译器,并且可能没有安全的方法在 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
我试图通过我的程序找到我的最大堆栈大小。我知道,在我的 OS 上,堆栈的最大大小约为 8MB。所以我试图进行无限循环,直到它导致分段错误。然后我需要打破这个循环,这样我才能计算大小。我怎样才能做到这一点?在 SIGSEGV 信号之后有什么办法可以打破无限循环吗?
static void handler(int signo)
{
if(signo == SIGSEGV)
{
printf("Waoh, caught signal\n");
}
}
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);
}
struct sigaction act;
act.sa_flags = SA_ONSTACK;
sigemptyset(&act.sa_mask);
act.sa_handler = handler;
sigaction(SIGSEGV, &act, NULL);
do
{
char a[counter];
counter += 8964;
} while (1);
return 0;
}
我修改了你的程序来计算堆栈大小的估计值,然后使用 siglongjmp 到 return 从信号处理程序到 main
就在分配可变长度数组的循环之前。 (请注意,可变长度数组的分配方式取决于编译器,并且可能没有安全的方法在 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