【问题标题】:Recursive coroutines in C (C99) [closed]C(C99)中的递归协程[关闭]
【发布时间】:2016-04-03 20:50:07
【问题描述】:

在实现通信协议时,我们有一个编码器,它递归地遍历一些结构并将它们编码成二进制消息。

到目前为止一切都很好,但是现在缓冲区必须分成多个固定大小的块,例如接收缓冲区的上限大小。由于为完整消息分配内存并因此切割它似乎太浪费了(消息的大小是--理论上-- 没有限制),现在的想法是实现一个协程setjmp/longjmp.

目前,我有一个带有两个跳转缓冲区的原型 - 一个用于恢复编码函数的缓冲区,第二个用于模拟函数的返回行为以跳转回其调用者。

嗯,它似乎工作,但代码看起来像是直接来自地狱。是否有任何“约定”来实现可中断的递归函数,可能是一组宏或其他东西?我想只使用标准化函数,而不是内联 asm 以保持便携性。

补充: 原型在这里:https://github.com/open62541/open62541/compare/master...chunking_longjmp “用法”显示在单元测试内部。 目前,协程行为是为非递归函数Array_encodeBinary 实现的。但是,“协程”行为应扩展到位于此处的通用递归 UA_encodeBinary 函数:https://github.com/open62541/open62541/blob/master/src/ua_types_encoding_binary.c#L1029

【问题讨论】:

  • ISO C 不支持您尝试做的事情。您使用setjmplongjmp 的方式不受标准的认可,并且在“便携式" C. 你可能会发现setcontext 和朋友有点更合适,因为它们实际上是为这个用例设计的,但它们并非在所有平台上都可用,而且使用起来仍然相当尴尬。
  • 您可以尝试为协程分配一个单独的堆栈,并使用setjmplongjmp 在递归协程和它的消费者之间切换。恐怕看不到任何可移植的东西,因为您可能不得不手动摆弄jmpbufs。
  • 听起来像是一种臃肿的方法和/或 XY 问题。鉴于这个问题太宽泛了。你的实际问题是什么?使用递归函数——在你写的关于浪费内存的文章中更是如此(那是嵌入式系统吗?)——大多数时候是个坏主意。
  • 您能发布您现有的代码吗?无意冒犯,但这听起来像是一个可怕的黑客攻击 [使用setjmp/longjmp]。我以前做过这种事情,我可以想出很多方法来做到这一点,这些方法很干净,但是有一些上下文可以帮助理解。
  • “二进制massage”现在听起来很放松,但我认为这是关于“二进制消息”。 :-)

标签: c recursion coroutine setjmp


【解决方案1】:

正如 Olaf 所指出的,最简单的方法是使用迭代算法。但是,如果由于某种原因这很困难,您始终可以使用stack 容器和while 循环来模拟递归算法。这至少使函数更容易被中断。可以在here 找到关于如何实现这一点的相当不错的文章。文章是为c++写的,不过转成c应该不难。

【讨论】:

  • 软件实现可能会出现与普通(硬件)堆栈相同的问题。实际上,它会增加更多的开销。无论如何,我不认为这是一个答案,而是更多的评论。
猜你喜欢
  • 1970-01-01
  • 2013-08-27
  • 1970-01-01
  • 2011-07-21
  • 2014-10-29
  • 2018-05-20
  • 2021-10-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多