C 语言 setjump() 和 longjump()2025年1月7日 | 阅读 6 分钟 setjmp() 和 longjmp() 函数用于在 C 程序中执行非局部跳转。它允许您从程序中的任何位置跳转回先前设置的跳转点。 setjmp() 函数将当前执行环境或上下文保存到 jmp_buf 变量中。它存储堆栈指针、寄存器等信息。首次调用时返回 0。 longjmp() 函数恢复由先前 setjmp() 调用保存的执行上下文。之后,它返回,因此执行将从 setjmp() 调用处恢复。然而,这一次,setjmp() 将返回一个非零值,表示 longjmp() 被调用,而不是直接调用 setjmp() 返回。 它允许您跳转到调用堆栈中先前保存的点。这对于错误处理场景非常有用,当您想从深度嵌套的函数调用中干净地回退时。 例如,setjmp() 可以在程序的顶层保存环境。然后,在某个嵌套函数深处,如果发生错误,longjmp() 可以跳回到调用 setjmp() 的顶层,而无需从每个嵌套函数层返回。 基本语法以下是 setjmp() 和 longjmp() 的基本语法 setjmp()
longjmp()
setjmp() 的工作原理以下是 setjmp() 在 C 程序中设置跳转点的工作原理说明 设置跳转点setjmp() 函数将当前执行状态/上下文保存到 'jmp_buf env' 参数指定的环境缓冲区中。此保存的状态包括:
它保存了 'jmp_buf env',代表一个可以稍后使用 'longjmp()' 返回的跳转点或检查点。 首次调用 'setjmp()'当首次调用 'setjmp()' 时,它会保存上述环境并返回 0。之后,执行将从 'setjmp()' 调用后正常继续。因此,第一次调用只是设置了稍后可以跳转回的检查点。 后续调用如果稍后调用 'longjmp()' 进行跳转,当环境恢复时,'setjmp()' 将被调用第二次。之后,'setjmp()' 将返回一个非零值。这个非零返回值是作为 'val' 参数传递给 'longjmp()' 的。 总而言之,第一次调用保存环境并返回 0。由 'longjmp()' 引起的后续调用返回 'longjmp(env, val)' 中的非零值,以指示发生了跳转。代码可以通过检查 'setjmp()' 返回 0 与否来判断是首次调用还是跳转返回。 setjmp()/longjmp() 实现非局部跳转,允许通过跳转到已保存点来处理错误/恢复。 longjmp() 的用法以下是 longjmp() 在 C 程序中执行非局部跳转的用法说明 执行非局部跳转'longjmp()' 函数恢复之前通过调用 'setjmp()' 保存的执行上下文。它有效地将执行跳转到 'setjmp()' 被调用的点。 然而,与第一次返回 0 不同,在 'longjmp()' 跳转回来后,'setjmp()' 将返回一个非零值,从而使程序能够检测到发生了跳转。 longjmp() 参数'longjmp()' 接受两个参数
这种非局部跳转能力为复杂情况下的错误处理和恢复提供了一种非常灵活的方式。 使用 setjmp() 和 longjmp() 进行错误处理setjmp()/longjmp() 的一个常见用例是处理深度嵌套函数调用中的错误。 例如 它允许 nestFunc1() 在发生问题时通过非局部跳转立即返回到错误处理块。 最佳实践
陷阱
总而言之,setjmp()/longjmp() 提供了一种非局部返回的方法,但必须小心处理,以避免在处理错误时产生副作用或泄漏。 范围和限制以下是关于正确使用 setjmp() 和 longjmp() 的范围和限制的一些关键点 恰当的用途
不推荐的用途
局限性
示例和代码片段以下是一些实际示例和代码片段,说明了 setjmp() 和 longjmp() 在不同上下文中的用法 示例:1输出 Start of main() Executing foo() Error handled in foo() End of main() 示例 2:跨函数的非局部跳转输出 Start of main() Inside foo() Inside bar() Jumped back to main() from longjmp() End of main() 示例 3:资源清理输出 Start of main() Performing a risky operation... Performing cleanup... 这些示例展示了 setjmp() 和 longjmp() 在不同上下文中的错误处理、非局部跳转和资源清理。它们提供了对这些函数如何在实际场景中应用的实际理解。 安全担忧
推荐
下一主题C 语言编程测试 |
我们请求您订阅我们的新闻通讯以获取最新更新。