我有我使用捕捉任何段故障或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()给了我错误的释放已经释放的内存。 我只是想只有一次免费的,但仍然不希望退出应用程序。
请帮忙。
对于像默认操作SIGSEGV
是终止的过程,但是因为你已经安装了一个处理程序,它会调用处理覆盖缺省行为。 但问题是指令段错误可能处理程序完成后重试,如果你有没有采取措施来修复第一赛格故障,重试的指令将再次故障,它的推移和。
因此,首先发现了导致指令SIGSEGV
并尝试修复它(你可以调用像backtrace()
的处理程序,看看自己哪里出了问题)
此外,POSIX标准说,
一个过程的行为是未定义它从一个信号捕获函数通常返回之后的[XSI] SIGBUS,SIGFPE,SIGILL,或)不是由杀灭(产生SIGSEGV信号,[RTS] sigqueue(),或提高( )。
所以,做理想的事情是解决您的段错误摆在首位。 处理程序段错误不意味着绕过底层错误条件
因此,最好的建议将是─ 不要赶上SIGSEGV
。 让它转储核心。 分析的核心。 修复无效的内存引用和你去那里!
我不同意所有的发言“不要赶上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\n");
return 0;
}
如果SIGSEGV
再次闪光,很明显的结论是,调用MyfreeBuffers();
没有固定的根本问题(如果该功能确实仅free()
一些分配的内存,我不知道为什么你会认为它会)。
粗略地说,一个SIGSEGV
当试图火灾访问无法访问的内存地址。 如果你不打算退出应用程序,你需要或者使该内存地址访问,或改变与执行路径longjmp()
你不应该尝试后继续SIG_SEGV
。 这基本上意味着你的应用程序的环境以某种方式被损坏。 这可能是你刚才提领一空指针,或者它可能是一些bug,导致您的程序堆栈损坏或堆或某些指针变量,你只是不知道。 唯一安全的事情就是终止程序。
这是完全合法的手柄控制-C。 应用大量的做,但你必须要非常小心你在信号处理程序做什么。 你不能调用不是重入的任何功能。 因此,这意味着,如果你的MyFreeBuffers()
调用STDLIB free()
函数,你可能搞砸了。 如果用户点击控制-C,而该计划是在中间malloc()
或free()
,因此中途操纵他们用它来追踪堆分配的数据结构,你几乎肯定会破坏堆,如果你调用malloc()
或free()
在信号处理程序。
你可以在信号处理程序做的唯一安全的做法是设置一个标志,说你抓住了信号。 然后,您的应用程序可以轮询的标志间隔,以决定是否需要执行一些动作。
那么,如果它没有设置,你可以设置一个状态变量,只可用内存。 信号处理程序将被称为每次,你无法控制AFAIK。
我可以看到的情况下从一个SIG_SEGV恢复,如果在一个循环,其中一个事件的处理事件导致分段违例,那么你只会想跳过这个事件,继续处理余下的事件。 在我的眼里SIG_SEGV类似于Java中的空指针异常。 是的状态将是后两种的这些矛盾和未知的,但是在某些情况下,你想处理的情况而矣。 例如,在算法中的交易,你会暂停订单的执行,并允许交易者手动接管,用了使整个系统崩溃,破坏其他所有订单。
看起来像使用的伎俩至少在Linux下用-fnon的呼叫例外选项可以解。 这将给予信号转换为普通C ++异常和通用的方式处理它的能力。 看linux3 / gcc46:“-fnon的呼叫例外”,这信号被俘获的指令? 例如。