因此,我有一个库(不是由我编写的),它不幸地使用abort()来处理某些错误。在应用程序级别,这些错误是可恢复的,所以我想处理它们,而不是让用户看到崩溃。所以我最后写了这样的代码:
static jmp_buf abort_buffer;
static void abort_handler(int) {
longjmp(abort_buffer, 1); // perhaps siglongjmp if available..
}
int function(int x, int y) {
struct sigaction new_sa;
struct sigaction old_sa;
sigemptyset(&new_sa.sa_mask);
new_sa.sa_handler = abort_handler;
sigaction(SIGABRT, &new_sa, &old_sa);
if(setjmp(abort_buffer)) {
sigaction(SIGABRT, &old_sa, 0);
return -1
}
// attempt to do some work here
int result = f(x, y); // may call abort!
sigaction(SIGABRT, &old_sa, 0);
return result;
}不是很优雅的代码。由于这个模式最终不得不在代码的几个地方重复,所以我想将它简化一点,并可能将它封装在一个可重用的对象中。我的第一次尝试是使用RAII来处理信号处理程序的设置/删除(因为每个函数都需要不同的错误处理)。所以我想出了这个:
template <int N>
struct signal_guard {
signal_guard(void (*f)(int)) {
sigemptyset(&new_sa.sa_mask);
new_sa.sa_handler = f;
sigaction(N, &new_sa, &old_sa);
}
~signal_guard() {
sigaction(N, &old_sa, 0);
}
private:
struct sigaction new_sa;
struct sigaction old_sa;
};
static jmp_buf abort_buffer;
static void abort_handler(int) {
longjmp(abort_buffer, 1);
}
int function(int x, int y) {
signal_guard<SIGABRT> sig_guard(abort_handler);
if(setjmp(abort_buffer)) {
return -1;
}
return f(x, y);
}当然,function的主体是多,这种方式更简单、更清晰,但是今天早上我想到了一个想法。,这是肯定的吗?,我的想法是:
setjmp/longjmp之间发生变化。longjmp到与setjmp和returning相同的堆栈帧中的位置,所以我允许代码执行编译器在函数的退出点发出的清理代码。但我还是觉得这可能是不确定的行为。你们觉得怎么样?
发布于 2011-03-22 16:17:28
我假设f位于第三方库/应用程序中,因为否则您只需将其修复为不调用abort。考虑到这一点,而且RAII可能或不可靠地在所有平台/编译器上产生正确的结果,那么您有几种选择。
abort并对其进行了LD_PRELOAD。然后控制中止时发生的事情,而不是在信号处理程序中。f。然后,您只需检查返回代码,如果它再次失败,使用更新的inputs.function,然后让它显式地手动执行设置/解压。在这种情况下,它仍然消除了复制粘贴。发布于 2011-03-22 21:29:03
实际上,我喜欢您的解决方案,并编写了一些类似的测试工具,以检查目标函数assert()是否与预期的一样。
我看不出有什么理由让这段代码调用未定义的行为。C标准似乎支持它:abort()产生的处理程序不受从处理程序调用库函数的限制。(注意:这是C99的7.14.1.1(5) --遗憾的是,我没有C90的副本,这是C++标准引用的版本)。
C++03添加了一个进一步的限制:如果任何自动对象都会被抛出的异常破坏,将控制转移到程序中的另一个(目标)点,那么在将控制权转移到同一个(目的地)点的抛出点上对longjmp(jbuf,val)的调用具有未定义的行为。我假设您的语句“没有变量是易失性的,或者在对setjmp/longjmp的调用之间进行更改”包括实例化任何自动的C++对象。(我想这是一些遗留的C库吧?)
POSIX异步信号安全性(或缺乏安全性)也不是一个问题-- abort()与程序执行同步地生成它的SIGABRT。
最大的担忧将是破坏第三方代码的全局状态:作者不太可能在abort()之前努力使状态保持一致。但是,如果你是正确的,没有变量变化,那么这不是一个问题。
如果一个对标准有更好理解的人能证明我是错的,我会感谢你的开悟。
https://stackoverflow.com/questions/5393859
复制相似问题