捕获 C 中的段错误
我有一个程序,有时会因指针运算而出现段错误。 我知道会发生这种情况,但我无法轻松地提前检查它是否出现段错误 - 我可以“预扫描”输入数据以查看它是否会导致段错误(这可能无法确定),或者我可以重新调整它以不使用指针算术,这将需要大量的工作,或者我可以尝试捕获段错误。 所以我的问题是:
1)在C语言中,我如何捕获段错误? 我知道操作系统中的某些会导致段错误,但是如果 C 程序出现段错误,那么它能做什么,比仅仅段错误
更优雅地结束呢?
2)这有多便携?
我认为这是一种非常不可移植的行为,因此如果您发布任何代码来捕获段错误,请告诉我它的作用。 我使用的是 Mac OS X,但我希望我的程序能够在尽可能多的平台上运行,并且我想看看我的选择是什么。
别担心 - 基本上我想做的就是打印一条更用户友好的错误消息并释放一些 malloc()
ed 内存,然后死掉。 我不打算忽略我遇到的所有段错误并继续前进。
I have a program that segfaults from pointer arithmetic sometimes. I know this happens, but I can't easily check ahead of time to see whether it segfaults or not - either I can "pre-scan" input data to see if it will cause a segfault (which can be impossible to determine), or I can refit it to not use pointer arithmetic, which would require a significantly larger amount of work, or I can try to catch a segfault. So my question:
1) How, in C, can I catch a segfault? I know something in the OS causes a segfault, but what can a C program do in the event that it segfaults to die a bit more gracefully than just Segmentation fault
?
2) How portable is this?
I imagine this is a highly unportable behavior, so if you post any code to catch a segfault, please tell me what it works on. I'm on Mac OS X but I'd like my program to work on as many platforms as it can and I want to see what my options are.
And don't worry - basically all I want to do is print a more user-friendly error message and free some malloc()
ed memory, and then die. I'm not planning on just ignoring all segfaults I get and plowing ahead.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您可以使用函数 signal 为信号安装新的信号处理程序:
类似于以下代码:
You can use the function signal to install a new signal handler for the signal:
Something like the following code:
您必须定义一个信号处理程序。 这是在 Unix 系统上使用函数
sigaction
完成的。 我在 Fedora 64 位和 32 位以及 Sun Solaris 上使用相同的代码完成了此操作。You have to define a signal handler. This is done on Unix systems using the function
sigaction
. I've done this with the same code on Fedora 64- and 32-bit, and on Sun Solaris.信号处理程序中的安全操作非常有限。 调用任何未知可重入的库函数都是不安全的,这将排除例如
free()
和printf()
。 最佳实践是设置一个变量并返回,但这对您没有多大帮助。 使用诸如write()
之类的系统调用也是安全的。请注意,在此处给出的两个回溯示例中,
backtrace_symbols_fd()
函数将是安全的,因为它直接使用原始 fd,但对fprintf()
的调用是不正确的,并应使用write()
来代替。The safe actions in a signal handler are very limited. It's unsafe to call any library function not known to be re-entrant, which will exclude, for example,
free()
andprintf()
. Best practice is to set a variable and return, but this doesn't help you very much. It's also safe to use system calls such aswrite()
.Note that in the two backtrace examples given here, the
backtrace_symbols_fd()
function will be safe because it uses the raw fd directly, but the call tofprintf()
is incorrect, and should be replaced by a use ofwrite()
.信号处理(相对)可以跨 UNIX 机器(包括 Mac 和 Linux)移植。 最大的区别在于异常详细信息,它作为参数传递给信号处理例程。 抱歉,但是如果您想打印更合理的错误消息(例如故障发生的位置和原因),您可能需要一堆 #ifdef ......
好吧,这里有一个代码片段供您使用首先:
您的任务是:
,您甚至可以修补 pc信号处理程序(到故障指令之后),然后继续。 然而,典型的信号处理程序要么 exit() 要么将 longjmp() 返回到 main 中的保存位置。
问候
signal handling is (relatively) portable across unix machines (this includes mac and linux). The big differences are in the exception detail, which is passed as argument to the signal handling routine. Sorrty, but you will probably need a bunch of #ifdefs for that, if you want to print more reasonable error messages (such as where and due to which address the fault happened) ...
ok, here is a code fragment for you to start with:
Your task is to:
in theory, you could even patch the pc in the signal handler (to after the faulting instruction), and proceed. However, typical signal handlers either exit() or to a longjmp() back into a save place in the main.
regards