您好我正在尝试测试代码以查看它是否旨在处理内存问题 不幸的是,我必须通过c-unit来做到这一点,它不能很好地处理分段错误(只是崩溃) 所以我的问题是我可以为我正在测试的代码添加一个信号处理程序,以允许它退出违规函数而不是退出整个程序吗?
基本上我可以修改以下处理程序以退出函数并返回到我的cunit框架吗?
void sighandler(int signo, siginfo_t *si, ucontext_t* context)
{
printf("Handler executed for signal %d\n", signo);
exit(0); /* can i replace this with exit from function? */
}
答案 0 :(得分:1)
这是一个类似的问题和答案(尽管语言错误,C ++): Catch Segfault or any other errors/exceptions/signals in C++ like catching exceptions in Java
我相信你所寻找的是一个例外代替你的exit(0)语句,但是Segmentation Fault也不例外,因此很难处理。这就是说,似乎C没有内置的异常处理。
无论如何,这里有关于c ++中接收的参考:http://www.cplusplus.com/doc/tutorial/exceptions/
我不确切知道你是如何使用这里的函数的,但也许你可以返回一个布尔值而不是void,如果布尔值为真,则从调用函数返回?
答案 1 :(得分:1)
可以使用信号处理程序加上setjmp
/ longjmp
。
我不确定这个解决方案有多可靠。它在我测试它时有效,但可能包含未定义的行为,所以不要依赖它。
同样重要的是要注意有缺陷的代码可能比分段错误做得更糟。例如,它可能会破坏内存,因此您的测试代码或其他经过测试的代码将会失败。
以下代码主要基于this answer。
#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
static void good_func(void)
{
int q, *p = &q;
printf("%s running\n", __FUNCTION__);
*p = 3;
}
static void bad_func(void)
{
int *p = NULL;
printf("%s running\n", __FUNCTION__);
*p = 3;
}
static jmp_buf context;
static void sig_handler(int signo)
{
longjmp(context, 1);
}
static void catch_segv(int catch)
{
struct sigaction sa;
if (catch) {
memset(&sa, 0, sizeof(struct sigaction));
sa.sa_handler = sig_handler;
sa.sa_flags = SA_RESTART;
sigaction(SIGSEGV, &sa, NULL);
} else {
sigemptyset(&sa);
sigaddset(&sa, SIGSEGV);
sigprocmask(SIG_UNBLOCK, &sa, NULL);
}
}
typedef void (*func_t)(void);
static int safe_run(func_t func)
{
catch_segv(1);
if (setjmp(context)) {
catch_segv(0);
return 0;
}
func();
catch_segv(0);
return 1;
}
int main()
{
printf("good_func is %s\n", safe_run(good_func) ? "good" : "bad");
printf("bad_func is %s\n", safe_run(bad_func) ? "good" : "bad");
return 0;
}
答案 2 :(得分:0)
如果您确切知道函数中预期会导致SEGV的内容,您可以尝试在信号处理程序中设置一个标志。 (实际上,请注意,您允许在信号处理程序中调用的函数集非常有限,因此设置标志几乎是您无论如何都可以做的。)
将您的标志变量声明为volatile int caused_segv = 0
,让您的信号处理程序设置为caused_segv = 1
,并在您的代码中,在执行可能引发SIGSEGV的操作后,检查caused_segv
是否为非零。< / p>
另请注意,根据POSIX.1,SIGFPE
,SIGILL
和SIGSEGV
被明确调出,以便在信号处理程序完成时,行为未定义。对于任何其他信号,“程序应在被中断时恢复执行。”
所以,你的问题的答案实际上是,你不能可靠地做你想做的事,因为让SIGSEGV
自动让你处于未定义的行为状态,但你可以使用我给的你上面试试。