分割故障处理分割故障处理(Segmentation fault handling)

2019-05-13 13:34发布

我有我使用捕捉任何段故障或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()给了我错误的释放已经释放的内存。 我只是想只有一次免费的,但仍然不希望退出应用程序。

请帮忙。

Answer 1:

对于像默认操作SIGSEGV是终止的过程,但是因为你已经安装了一个处理程序,它会调用处理覆盖缺省行为。 但问题是指令段错误可能处理程序完成后重试,如果你有没有采取措施来修复第一赛格故障,重试的指令将再次故障,它的推移和。

因此,首先发现了导致指令SIGSEGV并尝试修复它(你可以调用像backtrace()的处理程序,看看自己哪里出了问题)

此外,POSIX标准说,

一个过程的行为是未定义它从一个信号捕获函数通常返回之后的[XSI] SIGBUS,SIGFPE,SIGILL,或)不是由杀灭(产生SIGSEGV信号,[RTS] sigqueue(),或提高( )。

所以,做理想的事情是解决您的段错误摆在首位。 处理程序段错误不意味着绕过底层错误条件

因此,最好的建议将是─ 不要赶上SIGSEGV 。 让它转储核心。 分析的核心。 修复无效的内存引用和你去那里!



Answer 2:

我不同意所有的发言“不要赶上SIGSEGV”。

这是一个相当不错的初步实践,以应对突发情况。 而这更清洁,以应付NULL指针(由malloc的失败给出)与相关联的信号机制setjmp/longjmp ,而不是一直以来你的代码分发错误条件管理。

但是请注意,如果你用'的sigaction'上SEGV ,一定不要忘了说SA_NODEFERsa_flags -或者找到另一种方式来处理的事实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;
}


Answer 3:

如果SIGSEGV再次闪光,很明显的结论是,调用MyfreeBuffers(); 没有固定的根本问题(如果该功能确实仅free()一些分配的内存,我不知道为什么你会认为它会)。

粗略地说,一个SIGSEGV当试图火灾访问无法访问的内存地址。 如果你不打算退出应用程序,你需要或者使该内存地址访问,或改变与执行路径longjmp()



Answer 4:

你不应该尝试后继续SIG_SEGV 。 这基本上意味着你的应用程序的环境以某种方式被损坏。 这可能是你刚才提领一空指针,或者它可能是一些bug,导致您的程序堆栈损坏或堆或某些指针变量,你只是不知道。 唯一安全的事情就是终止程序。

这是完全合法的手柄控制-C。 应用大量的做,但你必须要非常小心你在信号处理程序做什么。 你不能调用不是重入的任何功能。 因此,这意味着,如果你的MyFreeBuffers()调用STDLIB free()函数,你可能搞砸了。 如果用户点击控制-C,而该计划是在中间malloc()free() ,因此中途操纵他们用它来追踪堆分配的数据结构,你几乎肯定会破坏堆,如果你调用malloc()free()在信号处理程序。

你可以在信号处理程序做的唯一安全的做法是设置一个标志,说你抓住了信号。 然后,您的应用程序可以轮询的标志间隔,以决定是否需要执行一些动作。



Answer 5:

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



Answer 6:

我可以看到的情况下从一个SIG_SEGV恢复,如果在一个循环,其中一个事件的处理事件导致分段违例,那么你只会想跳过这个事件,继续处理余下的事件。 在我的眼里SIG_SEGV类似于Java中的空指针异常。 是的状态将是后两种的这些矛盾和未知的,但是在某些情况下,你想处理的情况而矣。 例如,在算法中的交易,你会暂停订单的执行,并允许交易者手动接管,用了使整个系统崩溃,破坏其他所有订单。



Answer 7:

看起来像使用的伎俩至少在Linux下用-fnon的呼叫例外选项可以解。 这将给予信号转换为普通C ++异常和通用的方式处理它的能力。 看linux3 / gcc46:“-fnon的呼叫例外”,这信号被俘获的指令? 例如。



文章来源: Segmentation fault handling