分段错误处理

2024-10-12 10:28:00
admin
原创
105
摘要:问题描述:我有一个应用程序,用于捕获任何分段错误或 ctrl-c。使用下面的代码,我能够捕获分段错误,但处理程序被一次又一次地调用。我该如何阻止它们。供您参考,我不想退出我的应用程序。我只需要小心地释放所有损坏的缓冲区。是否可以?void SignalInit(void ) { struct sigacti...

问题描述:

我有一个应用程序,用于捕获任何分段错误或 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() 会给出释放已释放内存的错误。我只想释放一次,但仍然不想退出应用程序。

请帮忙。


解决方案 1:

此类事件的默认操作SIGSEGV是终止您的进程,但由于您已为其安装了处理程序,因此它将调用您的处理程序来覆盖默认行为。但问题是,在处理程序完成后,可能会重试分段错误指令,如果您未采取措施修复第一个分段错误,则重试的指令将再次出错,并不断重复。

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

此外,POSIX 标准还规定,

当进程从信号捕获函数正常返回 [XSI] SIGBUS、SIGFPE、SIGILL 或 SIGSEGV 信号(该信号不是由 kill()、[RTS] sigqueue() 或 raise() 生成的)后,其行为是未定义的。

因此,最理想的做法是首先修复段错误。段错误处理程序并非旨在绕过底层错误情况

因此,最好的建议是 -不要捕获SIGSEGV。让它转储核心。分析核心。修复无效的内存引用,然后就可以了!

解决方案 2:

我完全不同意“不要捕捉 SIGSEGV”的说法。

这是处理意外情况的非常好的做法。使用与 相关的信号机制来处理NULL指针(由 malloc 失败提供)setjmp/longjmp比在整个代码中分配错误情况管理要干净得多。

但请注意,如果您在上使用“sigaction” SEGV,则一定不要忘记说SA_NODEFER-sa_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
");

  return 0;
}

解决方案 3:

如果SIGSEGV再次触发,那么显而易见的结论是,对的调用MyfreeBuffers();没有解决根本问题(如果该函数确实只free()分配了一些内存,我不确定你为什么会认为它会这样做)。

大致来说,SIGSEGV当尝试访问无法访问的内存地址时会触发。如果您不打算退出应用程序,则需要使该内存地址可访问,或者使用 更改执行路径longjmp()

解决方案 4:

您不应该在 之后尝试继续SIG_SEGV。这基本上意味着您的应用程序的环境在某种程度上被破坏了。可能是您刚刚取消引用了一个空指针,也可能是某个错误导致您的程序破坏了其堆栈、堆或某个指针变量,您只是不知道。唯一安全的做法是终止程序。

处理 control-C 是完全合法的。许多应用程序都这样做,但您必须非常小心在信号处理程序中执行的操作。您不能调用任何不可重入的函数。这意味着如果您MyFreeBuffers()调用 stdlib函数,您可能会陷入困境。如果用户在程序处于或free()中间时按下 control-C ,从而在操纵用于跟踪堆分配的数据结构的过程中途按下 或,则如果您在信号处理程序中调用或,则几乎肯定会破坏堆。malloc()`free()malloc()free()`

在信号处理程序中,唯一可以安全执行的操作就是设置一个标志,表示您捕获了信号。然后,您的应用可以定期轮询该标志,以决定是否需要执行某些操作。

解决方案 5:

好吧,您可以设置一个状态变量,并且只有在未设置时才释放内存。每次都会调用信号处理程序,据我所知您无法控制这一点。

解决方案 6:

我可以看到从 SIG_SEGV 中恢复的情况,如果您在循环中处理事件,并且其中一个事件导致分段违规,那么您只想跳过此事件,继续处理其余事件。在我看来,SIG_SEGV 类似于 Java 中的 NullPointerException。是的,在这两种情况之后,状态将不一致且未知,但是在某些情况下,您希望处理这种情况并继续。例如,在 Algo 交易中,您可以暂停订单的执行并允许交易者手动接管,而不会导致整个系统崩溃并破坏所有其他订单。

解决方案 7:

看起来至少在 Linux 下使用 -fnon-call-exceptions 选项的技巧可以解决问题。它将能够将信号转换为一般的 C++ 异常并以一般方式处理它。例如,查看linux3/gcc46:“-fnon-call-exceptions”,哪些信号是捕获指令?

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   681  
  在项目管理领域,集成产品开发(IPD)流程以其高效、协同的特点,被众多企业视为提升产品竞争力的关键。IPD流程强调跨部门、跨职能的紧密合作,以确保产品从概念到市场各个环节的无缝衔接。然而,实现这一目标并非易事,它需要企业深刻理解并掌握IPD流程中的跨部门协作艺术。本文将深入探讨IPD流程中跨部门协作的三个关键点,旨在为...
IPD项目管理咨询   9  
  掌握IPD流程图:提升团队协作的关键路径在当今快速变化的商业环境中,团队协作的效率与效果直接关系到项目的成功与否。集成产品开发(Integrated Product Development,简称IPD)作为一种先进的研发管理理念,通过跨部门、跨领域的协同工作,能够显著提升产品开发的速度与质量。而IPD流程图,则是这一理...
IPD流程阶段   9  
  IPD流程概述:理解其核心价值与实施背景集成产品开发(Integrated Product Development,简称IPD)是一种先进的产品开发管理理念,它强调跨部门协作、市场导向和快速响应变化的能力。IPD流程不仅关注产品本身的技术创新,更注重将市场、研发、生产、销售等各个环节紧密集成,以实现产品从概念到市场的高...
华为IPD是什么   7  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程以其跨部门协作、高效决策和快速响应市场变化的特点,被众多企业视为提升竞争力的关键。然而,实践IPD流程并非易事,项目管理中的种种错误往往阻碍了其效果的充分发挥。本文旨在深入探讨如何在实施IPD流程时避免这些常见错误,...
IPD框架   7  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用