c – longjmp和RAII
发布时间:2020-12-16 05:31:18 所属栏目:百科 来源:网络整理
导读:所以我有一个图书馆(不是我写的),不幸的是使用abort()来处理某些错误.在应用程序级别,这些错误是可恢复的,所以我想处理它们,而不是看到崩溃的用户.所以我最终写这样的代码: static jmp_buf abort_buffer;static void abort_handler(int) { longjmp(abort_bu
所以我有一个图书馆(不是我写的),不幸的是使用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,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,&old_sa); } ~signal_guard() { sigaction(N,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); } 当然这个功能的身体要简单得多,但是今天早上我想到了一个想法.这是否保证工作?这是我的想法: >没有任何变量在调用setjmp / longjmp之间是易变的或变化的. 但我仍然觉得这可能是未定义的行为.你们有什么感想? 解决方法
我假设f在第三方库/应用程序,因为否则你可以修复它,不要中止.鉴于此,RAII可能会或可能无法在所有平台/编译器上产生正确的结果,您可以选择几个.
>创建一个定义中止和LD_PRELOAD的小型共享对象.然后,您可以控制在中止时发生的情况,而不是在信号处理程序中.>在子进程内运行f.然后,您只需检查返回代码,如果失败,再次尝试更新输入.>而不是使用RAII,只需从多个呼叫点调用您的原始功能,并让它明确地手动进行设置/拆卸.在这种情况下,它仍然消除了复制粘贴. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |