回到一些C工作.
我的许多功能看起来像这样:
int err = do_something(arg1, arg2, arg3, &result);
Run Code Online (Sandbox Code Playgroud)
意图结果由函数填充,返回值是调用的状态.
黑暗面是你得到这样的天真:
int err = func1(...);
if (!err) {
err = func2(...);
if (!err) {
err = func3(...);
}
}
return err;
Run Code Online (Sandbox Code Playgroud)
我想我可以宏观:
#define ERR(x) if (!err) { err = (x) }
int err = 0;
ERR(func1(...));
ERR(func2(...));
ERR(func3(...));
return err;
Run Code Online (Sandbox Code Playgroud)
但这只有在我连接函数调用时才有效,而不是做其他工作.
显然,Java,C#,C++有一些例外,可以很好地处理这些事情.
我只是好奇其他人做了什么,以及其他人如何在他们的C程序中进行错误处理.
我们经常编写一些具有多个出口点的函数(即return在C中).同时,当退出函数时,对于一些常规工作,例如资源清理,我们希望只实现一次,而不是在每个出口点实现它们.通常,我们可以通过使用如下所示的goto来实现我们的愿望:
void f()
{
...
...{..{... if(exit_cond) goto f_exit; }..}..
...
f_exit:
some general work such as cleanup
}
Run Code Online (Sandbox Code Playgroud)
我认为在这里使用goto是可以接受的,我知道很多人同意在这里使用goto.出于好奇,是否有任何优雅的方式可以在C中不使用goto而整齐地退出函数?
我在C中编写并发事务库,发现了以下问题.让我们考虑一个示例事务成员伪代码,其中"transaction"表示与事务主机的通信通道:
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");
}
Run Code Online (Sandbox Code Playgroud)
在并发交易中,我们只有在被要求主人投票时才能投票.但是,主服务器可以随时调用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. */
Run Code Online (Sandbox Code Playgroud)
但是,为每次调用编写 …