在C中捕获段错误

Chr*_*utz 9 c macos error-handling segmentation-fault

我有一个程序,有时会从指针算术中发生段错误.我知道这种情况会发生,但是我不能提前检查它是否是段错误 - 要么我可以"预扫描"输入数据以查看它是否会导致段错误(这是无法确定的),或者我可以修改它不使用指针算法,这将需要大量的工作,或者我可以尝试捕获段错误.所以我的问题:

1)如何在C中捕获段错误?我知道操作系统中的某些内容会导致段错误,但是C程序可以做的事情是,如果它会比仅仅更优雅地使用段错误而死掉它们Segmentation fault

2)这有多便携?

我想这是一个非常不可移植的行为,所以如果你发布任何代码来捕获段错误,请告诉我它的工作原理.我在Mac OS X上,但我希望我的程序可以在尽可能多的平台上工作,我想知道我的选择是什么.

并且不用担心 - 基本上我想要做的就是打印一个更加用户友好的错误消息并释放一些malloc()内存,然后死掉.我不打算只是忽略我得到的所有段错误并继续前进.

Pau*_*ham 21

那么,SIGSEGV是可以捕获的,这是POSIX,所以它在这个意义上是可移植的.

我担心你似乎想要处理段错误,而不是解决导致段错误的问题.如果我不得不选择是故障操作系统还是我自己的代码,我知道我会选择哪个.我建议你找出那个bug,修复它,然后写一个测试用例,以确保它再也不会咬你.


Igo*_*Oks 12

您可以使用函数信号信号安装新的信号处理程序:

   #include <signal.h>
   void (*signal(int signum, void (*sighandler)(int)))(int);
Run Code Online (Sandbox Code Playgroud)

类似下面的代码:

signal(SIGINT , clean_exit_on_sig);
signal(SIGABRT , clean_exit_on_sig);
signal(SIGILL , clean_exit_on_sig);
signal(SIGFPE , clean_exit_on_sig);
signal(SIGSEGV, clean_exit_on_sig); // <-- this one is for segmentation fault
signal(SIGTERM , clean_exit_on_sig);

void 
clean_exit_on_sig(int sig_num)
{
        printf ("\n Signal %d received",sig_num);
}
Run Code Online (Sandbox Code Playgroud)


Sco*_*e T 9

您必须定义一个信号处理程序.这是在使用该功能的Unix系统上完成的sigaction.我在Fedora 64-和32位以及Sun Solaris上使用相同的代码完成了这项工作.


Dal*_*und 5

信号处理程序中的安全操作非常有限.调用任何未知的可重入的库函数是不安全的,例如,将排除free()printf().最佳做法是设置变量并返回,但这对您没有多大帮助.使用系统调用也是安全的write().

请注意,在此处给出的两个回溯示例中,该backtrace_symbols_fd()函数将是安全的,因为它直接使用原始fd,但调用fprintf()不正确,应该替换为使用write().