使用longjmp / setjmp进行Cerror handling有哪些“好”的方法?

我必须将C用于一个项目,我正在考虑使用longjmp/setjmp进行error handling,因为我认为在一个中心位置处理错误要比返回代码容易得多。 如果有一些关于如何做到这一点的线索,我将不胜感激。

如果发生任何此类错误,我特别关注正确完成资源清理。

另外,我如何处理导致multithreading程序使用它们的错误?

更好的是,是否有一些C库已经存在以进行错误/exception处理?

如果你担心资源清理,你必须认真地想知道longjmp()和setjmp()是否是一个好主意。

如果您设计资源分配系统以便实际上可以准确地进行清理,那么就可以了 – 但是这种设计往往很棘手,而且如果事实上您的代码自己使用的标准库分配了必须的资源,那么这种设计通常是不完整的被发布。 它需要特别小心,并且因为它不完全可靠,所以它不适合长时间运行的系统,它们可能需要经历多次使用setjmp()/ longjmp()调用(它们会泄漏,扩展并最终导致问题)。

Symbian根据longjmp()实现了它的Leave机制,这可以很好地了解你需要做的所有事情。

Symbian有一个全局的“清理堆栈”,如果发生跳转,你可以推送和弹出你想要清理的东西。 这是C ++编译器在抛出C ++exception时执行的自动堆栈展开的手动替代方法。

Symbian有“陷阱”,它会跳出来; 这些可以嵌套。

(最近,Symbian在C ++exception方面重新实现了它,但接口保持不变)。

总而言之,我认为正确的C ++exception不易编码错误,而且比滚动自己的C等价物要快得多。

(例如,现代C ++编译器非常擅长“零开销”exception,例如; longjmp()必须存储所有寄存器的状态,即使在以后不进行跳转时也是如此,因此从根本上说,和exception一样快。)

使用C ++作为更好的C,只采用exception和RAII,如果使用longjmp()进行exception仿真,那么这将是一个很好的途径。

我只发现了一个用于setjmp()/longjmp()用法,它与error handling无关。

实际上没有必要使用它,因为它总是可以重构为更容易遵循的东西。 setjmp()/longjmp()的使用与goto非常相似,因为它很容易被滥用。 任何使你的代码可读性降低的东西一般都是个坏主意。 请注意,我并不是说它们本身就很糟糕,只是因为它们比其他选择更容易导致代码错误。

FWIW,他们非常宝贵的一个地方是我在行业早期做的一个项目(MS-DOS 6时间框架)。 我设法使用Turbo C组建了一个合作multithreading库,它在yield()函数中使用这些函数来切换任务。

从那些日子开始,我很确定我没有碰过它们(或者有必要)。

例外是迄今为止更好的通用机制,但在C过去的黑暗时期,我写了一个包含命令shell的处理器模拟器。 用于setjmp / longjmp的shell用于中断处理(即处理器正在运行,用户命中break / ctrl-c,代码将SIGINT和longjmps捕获回shell)。

我已经合理地使用了setjmp / longjmp ,以便在回调中逃脱,而不必通过各种其他库级别协商。

那种情况(如果我没记错的话)是yacc生成的解析器中的代码可以检测到(非语法)问题,并且想要放弃解析但是将一个相当有用的错误报告返回给另一方的调用者。所有yacc生成的代码。 另一个例子是在一个从Expat解析器调用的回调中。 在每种情况下,还有其他方法可以做到这一点,但它们似乎比以这种方式拯救更加繁琐和模糊。

正如其他答案所指出的那样,有必要小心清理,并且非常考虑确保longjmp代码只能在由setjmp动态保护的区域范围内调用。

在multithreading编程的上下文中做到这一点? 我确信这并非不可能,但是哦:现在就拿出你的家庭装阿司匹林。 将setjmp / longjmp对尽可能保持在一起可能是明智之举。 只要匹配的setjmp / longjmp对在同一个线程中,我希望你会好的,但是……小心那里。