【问题标题】:How to simulate exceptions in C with goto?如何使用 goto 在 C 中模拟异常?
【发布时间】:2009-06-03 09:26:17
【问题描述】:

我正在用 C 编写一个并发事务库,发现了以下问题。让我们考虑一个示例事务成员伪代码,其中“事务”表示与事务主机的通信通道:

transaction = trans_join();

do_some_ops();

/* receive the data from the master */
trans_rcv(transaction, data);

do_some_ops();

trans_send(transaction, answer);

/* wait for the possibility for voting */
trans_ready(transaction);

/* vote for commiting and wait for the voting results. */
if(trans_commit(answer))
{
   printf("Final commiting the changes.\n");
}
else
{
   printf("Rolling back the changes.\n");
}

在并发事务中,只有当主节点要求我们投票时,我们才能投票。但是master可以随时调用trans_abort(member),强制指定成员取消交易。成员可以在执行的任何阶段接收到 ABORT 消息,在这种情况下,它不应该等到执行到达trans_ready() 调用。例如,如果在后面的代码中有一个trans_rcv() 调用,则该进程将一直等待来自主服务器的数据,这些数据永远不会发送。

现在,重点。我已经有代码来注册回滚更改的中止函数,但我还希望有一个额外的机制,允许跳过其余的操作并立即跳转到投票代码。我有个想法,在这里使用 goto 来模拟异常:

if(!trans_rcv()) /* fail, we received the abort message */
{
   goto abort_code;
}

...

abort_code:
trans_ready(transaction);
/* etc. */

然而,为trans_rcvtrans_send 的每次调用编写ifs 并不是很舒服,尤其是在事务代码复杂的情况下。您对更好的解决方案有任何想法还是这是唯一的方法?顺便说一句,它不必使用goto :)。

【问题讨论】:

  • 让我们看看有多少人会带着“goto?AAAAAAAAAAAAARGH”之类的东西来:P

标签: c exception goto


【解决方案1】:

goto 只能在一个函数内工作,这可能是异常机制的过多限制。

我建议使用 setjmp/longjmp 函数 - 有关详细信息,请参阅 Wikipedia

【讨论】:

    【解决方案2】:

    如果键入 IF 有问题,您可以使用宏,例如:

    #define trans_rcv_CHK do { \
         if (!trans_rcv()) \
         { \
              goto abort_code; \
         } \
    } while(0)
    

    如果 trans_rcv 有参数,这应该可以工作(至少在 gcc 中):

    #define trans_rcv_CHK(...) do { \
         if (!trans_rcv(__VA_ARGS__)) \
         { \
              goto abort_code; \
         } \
    } while (0)
    

    【讨论】:

    • 宏......我忘记它们真是太奇怪了。提前致谢!
    • 确保将 if 包装在 do while false 中。那让我们在最后用分号调用 trans_rcv_CHK 并且不会产生任何意想不到的后果。见:c2.com/cgi/wiki/Wiki?TrivialDoWhileLoop
    【解决方案3】:

    就我个人而言,我会使用一个带有基于开关的状态机的 while 循环来编写代码。

    【讨论】:

      【解决方案4】:

      exception handling in C 的最佳来源之一。基本上,RTOS 的人们如何为他们的 RTFile 模块实现异常。谨防在文章后半部分可怕地滑入汇编语言。

      【讨论】:

        【解决方案5】:

        参见 Hanson 的“C Interfaces and Implementations: Techniques for Creating Reusable Software”。它提供了一种基于setjmp()longjmp() 的异常机制。该代码可通过 MIT 许可证获得。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-11-16
          • 2015-11-06
          • 2013-01-24
          • 1970-01-01
          • 2021-09-08
          • 1970-01-01
          • 2011-02-16
          • 1970-01-01
          相关资源
          最近更新 更多