SIGSEGV 处理程序中的段错误

编程入门 行业动态 更新时间:2024-10-18 01:41:36
本文介绍了SIGSEGV 处理程序中的段错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

假设我有以下 C 代码:

static void handler(int sig, siginfo_t *si, void *unused){printf("BOOM! ");//这里的另一个段错误退出(-1);}int main(int argc, char *argv[]){结构 sigaction sa;sa.sa_flags = SA_SIGINFO;sigemptyset(&sa.sa_mask);sa.sa_sigaction = 处理程序;if (sigaction(SIGSEGV, &sa, NULL) == -1)perror("设置处理程序失败");//在这里调用其他东西,在调用堆栈的某个地方发生了段错误}

如果执行遇到第一个分段错误,则将触发处理程序.但是当处理程序本身由于某种原因发生分段错误时会发生什么?它会用新的 siginfo_t 再次调用处理程序还是会立即终止程序?

如果再次调用处理程序,类似这样的工作:

int in_handler = 0;静态无效处理程序(int sig,siginfo_t *si,无效*未使用){printf("BOOM! ");如果(!in_handler){in_handler = 1;//可能出现段错误的代码} 别的 {//完全安全的代码}退出(-1);}

我问的原因是我目前正在用 C 语言编写某种单元测试框架.如果测试用例由于某些非法内存访问而失败,我想将所有剩余的测试标记为失败.如果由于某种原因测试严重破坏了堆,则此操作可能会失败,因为我必须遍历数据结构并将该信息写入 xml 文件.但是,如果将所有剩余的测试都标记为失败,我仍然希望保留哪些测试是失败的信息.

解决方案

来自 sigaction(2):

#include <signal.h>int sigaction(int signum, const struct sigaction *act, struct sigaction*旧行为);……

sigaction 结构被定义为类似

struct sigaction {无效 (*sa_handler)(int);无效 (*sa_sigaction)(int, siginfo_t *, 无效 *);sigset_t sa_mask;int sa_flags;无效(*sa_restorer)(无效);}

....

sa_mask 给出一个信号掩码,在信号处理程序的执行.此外,该信号触发处理程序将被阻止,除非 SA_NODEFER 标志是用过.

因为您在设置信号处理程序时没有设置 SA_NODEFER 标志,所以如果在信号处理程序中发生另一个段错误,则不会再次调用它仍在信号处理程序中.一旦退出,之前被阻塞的信号就会被传递出去.

Lets assume I have the following C code:

static void handler(int sig, siginfo_t *si, void *unused) { printf("BOOM! "); //another segfault here exit(-1); } int main(int argc, char *argv[]) { struct sigaction sa; sa.sa_flags = SA_SIGINFO; sigemptyset(&sa.sa_mask); sa.sa_sigaction = handler; if (sigaction(SIGSEGV, &sa, NULL) == -1) perror("failed to set handler"); // call other stuff here, somewhere in the callstack a segfault happens }

If the execution hits the first segmentation fault the handler will be triggered. But what happens when in the handler itself from some reason a segmentation fault happens? Will it call the handler again with the new siginfo_t or will the program be terminated immediately?

If the handler is called again would something like this work:

int in_handler = 0; static void handler(int sig, siginfo_t *si, void *unused) { printf("BOOM! "); if(!in_handler) { in_handler = 1; //code that could possibly segfault } else { //totally safe code } exit(-1); }

The reason why I'm asking is that I'm currently writing some sort of unit test framework in C. If a testcase failed due to some illegal memory access I would like to mark all remaining tests as failed. If for some reason the test hast screwed up the heap really badly this operation could fail because I have to iterate over a data structure and write that information to a xml file. But if marking all remaining tests as failed I would still like to preserver the information which test was the failing one.

解决方案

From the man page for sigaction(2):

#include <signal.h> int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); ....

The sigaction structure is defined as something like

struct sigaction { void (*sa_handler)(int); void (*sa_sigaction)(int, siginfo_t *, void *); sigset_t sa_mask; int sa_flags; void (*sa_restorer)(void); }

....

sa_mask gives a mask of signals which should be blocked during execu- tion of the signal handler. In addition, the signal which triggered the handler will be blocked, unless the SA_NODEFER flag is used.

Because you didn't set the SA_NODEFER flag when setting up your signal handler, it won't get called again if another segfault occurs while still in the signal handler. Once you exit, the signal which was previously blocked will then be delivered.

更多推荐

SIGSEGV 处理程序中的段错误

本文发布于:2023-10-09 05:51:49,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1474881.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:错误   程序   SIGSEGV

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!