我是一名C ++程序员,习惯了具有良好异常处理能力的OO语言。
据我了解,setjmp和longjmp本质上是一种c样式的传播异常条件的方式。它们似乎还像是goto的强烈形式,可以提升堆栈。
因此,首先:好的做法是在当前时间点在C语言中直接使用它们,还是不建议使用它们? (注意:C不是C ++)。
其次,它们在C ++中有什么用,还是我认为它们是被C ++的异常处理功能所取代的旧机制,我是否正确?
从本质上讲,您认为jmp
样式的传播与goto
本质上是一样的。阅读有关Dijkstra's (famous and controversial) paper的goto
,(我认为)为为什么很少使用goto
提供了合理的理由。除非您确切地知道为什么要做自己的工作(或者您在非常特定的领域(例如嵌入式编程)中工作),否则请勿触摸goto
或longjmp
。
它们用于实现协程。网上有几个C ++协程库,在Unix / Linux中它们将使用setjmp/longjmp
实现该功能。
因此,如果您的目标是实现协程库,那么不管它是否是一个好的实践,这都是有争议的,因为在那些平台上,这是支持该功能的唯一方法。
如果您的目标是使用协程库,则应搜索其中一些。甚至还有一个名为boost :: context的Boost Vault提议,该提议已经被批准。
setjmp/longjmp
有一些正确的用法。用它们实现协程实际上是不可能的,因为您必须使用(非便携式)技巧(请参阅:内联汇编)来切换堆栈。
setjmp/longjmp
的一种用法是捕获浮点信号,但这会使C ++堆栈展开变得混乱。不过在C中正确。
您还可以实现某种形式的堆栈展开(通过维护您自己的清理处理程序堆栈),并使用C在它们中实现真正的析构函数和异常。这在大型项目中非常方便:缺少正确的错误处理机制是C的弱点。但是,正确执行它非常困难,并且您必须编写一堆宏才能简化任务。
setjmp
,因为您说那是例外。您也不想在C中使用它们,因为很难正确实现。尽力寻找其他解决方案。setjmp
和longjmp
是用于绕过正常函数调用和返回流的宏。setjmp
保存要由longjmp
使用的呼叫环境正确使用这些宏确实非常困难,并且您很容易以未定义的行为结束。因此,例如,必须将longjmp
限制为1级信号处理程序(最好实际上根本不被调用)。在关键系统中,完全不需要使用。