分段error handling

我有一个应用程序,我用它来捕捉任何分段错误或ctrl-c。 使用下面的代码,我能够捕捉到分段错误,但处理程序被一次又一次地调用。 我怎样才能阻止他们。 为了您的信息,我不想退出我的应用程序。 我只需要注意释放所有损坏的缓冲区。

可能吗?

void SignalInit(void ) { struct sigaction sigIntHandler; sigIntHandler.sa_handler = mysighandler; sigemptyset(&sigIntHandler.sa_mask); sigIntHandler.sa_flags = 0; sigaction(SIGINT, &sigIntHandler, NULL); sigaction(SIGSEGV, &sigIntHandler, NULL); } 

和处理程序是这样的。

 void mysighandler() { MyfreeBuffers(); /*related to my applciation*/ } 

在这里为分段错误信号,处理程序被调用多次,正如显而易见MyfreeBuffers()给我释放已释放内存的错误。 我只想释放一次,但仍然不想退出应用程序。

请帮忙。

Solutions Collecting From Web of "分段error handling"

SIGSEGV这样的默认动作是终止你的进程,但是你已经为它安装了一个处理程序,它会调用你的处理程序覆盖默认的行为。 但是,问题是segfaulting指令可能会在处理程序结束后重试,如果没有采取措施修复第一个seg故障,则重试指令将再次出错并继续运行。

因此,首先找到导致SIGSEGV的指令并尝试修复它(可以在处理程序中调用类似于backtrace()东西,并亲自看看出了什么问题)

另外,POSIX标准说,

(),[RTS] sigqueue()或raise()生成的[XSI] SIGBUS,SIGFPE,SIGILL或SIGSEGV信号的信号捕获函数正常返回时,进程的行为是不确定的)。

所以,理想的做法是首先解决您的段错误。 处理段错误并不意味着绕过潜在的错误条件

所以最好的建议是 – 不要赶上SIGSEGV 。 让它倾倒核心。 分析核心。 修复无效的内存引用,你去!

如果SIGSEGV再次触发,显而易见的结果是调用MyfreeBuffers(); 没有解决底层的问题(如果该函数真的只free()一些分配的内存,我不知道为什么你会认为它会)。

粗略地说,一个SIGSEGV在试图访问一个不可访问的内存地址时触发。 如果您不打算退出应用程序,则需要使该内存地址可访问,或使用longjmp()更改执行路径。

我完全不同意“不要抓住SIGSEGV”的说法。

处理意外情况是一个很好的实践。 而且,处理与setjmp/longjmp关联的信号机制的NULL指针(如malloc失败给出的)要比处理整个代码的错误条件管理要干净得多。

不过要注意的是,如果你在SEGV上使用'sigaction',你不能忘记在sa_flags声明SA_NODEFER ,或者找另一种方法来处理SEGV只会触发你的处理程序一次。

 #include <setjmp.h> #include <signal.h> #include <stdio.h> #include <string.h> static void do_segv() { int *segv; segv = 0; /* malloc(a_huge_amount); */ *segv = 1; } sigjmp_buf point; static void handler(int sig, siginfo_t *dont_care, void *dont_care_either) { longjmp(point, 1); } int main() { struct sigaction sa; memset(&sa, 0, sizeof(sigaction)); sigemptyset(&sa.sa_mask); sa.sa_flags = SA_NODEFER; sa.sa_sigaction = handler; sigaction(SIGSEGV, &sa, NULL); /* ignore whether it works or not */ if (setjmp(point) == 0) do_segv(); else fprintf(stderr, "rather unexpected error\n"); return 0; } 

您不应该在SIG_SEGV之后继续尝试。 这基本上意味着你的应用程序的环境在某种程度上被破坏了。 这可能是因为你只是解引用了一个空指针,或者可能是某个bug导致你的程序破坏了它的堆栈或堆或者一些指针变量,你只是不知道。 唯一安全的事情就是终止程序。

处理控制C是完全合法的。 许多应用程序都这样做,但是您必须非常小心您在信号处理程序中所做的工作。 你不能调用任何不可重入的函数。 所以这意味着如果你的MyFreeBuffers()调用了stdlib的free()函数,你可能会搞砸了。 如果用户在程序处于malloc()free()的中间时碰到control-C,并且因此通过操纵用于跟踪堆分配的数据结构来达到一半,那么如果调用malloc() ,几乎肯定会损坏堆malloc()free()在信号处理程序。

关于在信号处理程序中可以做的唯一安全的事情是设置一个标志,说你发现了信号。 然后,您的应用程序可以间隔轮询该标志,以确定是否需要执行某个操作。

那么你可以设置一个状态变量,只有空闲的内存,如果没有设置。 信号处理程序将每次被调用,您无法控制该AFAIK。

我可以看到从SIG_SEGV恢复的情况下,如果您在循环中处理事件并且其中一个事件导致了Segmentation Violation,那么您只想跳过此事件,继续处理其余的事件。 在我看来,SIG_SEGV类似于Java中的NullPointerException。 是的,在这两种情况之一后,国家将是不一致的和不明的,但是在某些情况下,您想要处理这种情况并继续进行下去。 例如,在Algo交易中,您可以暂停执行订单,并允许交易者手动接管,整个系统崩溃并破坏所有其他订单。

看起来至少在Linux下使用-fnon-call-exceptions选项可以解决这个问题。 它将提供将信号转换为一般C ++异常并通过一般方式处理的能力。 看看linux3 / gcc46:“-fnon-call-exceptions”,哪个信号是陷阱指令? 例如。