C 良好实践-功能终止时有很多工作要做-转到备选方案

C 良好实践-功能终止时有很多工作要做-转到备选方案,c,goto,C,Goto,可能重复: 最近我遇到了这样的C代码: if(!condition1){ 后继失败; } 有些东西需要手动拆除(); 如果(!条件2){ 后继失败; } //还有更多的线路,比如上面的线路 返回0; 失败: //在这里做很多事情,免费,关闭文件等等 返回-1; 总结一下情况: 我有一个很长的函数,可以在一行中完成几件事情(比如打开一个文件,然后根据文件内容分配内存,然后连接数据库等等)。当然,我希望正确地释放资源,但是有很多地方可能会导致函数过早结束(所有这些地方都需要清理) 问题是:如何正

可能重复:

最近我遇到了这样的C代码:

if(!condition1){
后继失败;
}
有些东西需要手动拆除();
如果(!条件2){
后继失败;
}
//还有更多的线路,比如上面的线路
返回0;
失败:
//在这里做很多事情,免费,关闭文件等等
返回-1;
总结一下情况:

我有一个很长的函数,可以在一行中完成几件事情(比如打开一个文件,然后根据文件内容分配内存,然后连接数据库等等)。当然,我希望正确地释放资源,但是有很多地方可能会导致函数过早结束(所有这些地方都需要清理)

问题是:如何正确地做到这一点?

虽然
goto

我认为:

使用可执行此任务的宏,例如:
#定义清除如果(内存!=NULL)空闲(内存)\
如果(fp!=NULL)fclose(fp)\
// ...
如果(!条件1){
清理
返回-1;
}
如果(!条件2){
清理
返回-2;
}
// ...
这将导致重复的程序集,但清理代码将位于一个位置

将函数封装到另一个函数中
int\u一些东西工作(无效**内存,文件**文件,…){
//只会在出错时返回
}
int一些东西(){
空*内存=空;
FILE*FILE=NULL;
_一些工作(内存、文件等);
if(fp)fclose(fp);
}
如果有超过3-5件事情需要清理,这可能会变得非常糟糕(该函数将接受许多参数,并且总是需要一个问题)

面向对象析构函数
typedef结构{
空*内存;
文件*fp;
}本地数据;
//析构函数
作废本地数据销毁(本地数据*数据)
{
如果(数据->fp){
免费(数据->fp);
数据->fp=NULL;
}
}
但这可能会导致许多函数(和结构)在整个应用程序中只使用一次,而且看起来可能会产生大量的功能

循环和中断语句
while(1){
如果(!条件1){
打破
}
// ...
打破
}
if(fp)fclose(fp);

我在may places上发现了这个,但是使用了一个迭代循环?我不知道,这似乎是完全不直观的。

去吧。首先要明白为什么“后藤是坏的”,然后你们会发现在你们描述的情况下后藤并不是真的坏。不惜一切代价避免goto是错误的,它来自于对良好编程原则的肤浅理解

这就是方法(Linux内核源代码):

后路是必由之路。首先要明白为什么“后藤是坏的”,然后你们会发现在你们描述的情况下后藤并不是真的坏。不惜一切代价避免goto是错误的,它来自于对良好编程原则的肤浅理解

这就是方法(Linux内核源代码):

还有另一种可能性:
do{/*…*/}while(false)
break
语句。实际上,我认为从这些解决方案中,带有
goto
的原始代码是最好的Vyktor,在将指针传递到
free
之前,不需要检查NULL。它保证忽略
NULL
指针。这不像10年前那样是真的,但现在这些检查没有意义了。@DyP对此表示感谢,但忘了放下它,补充道。在函数中清理并拥有一个退出点是goto完美的情况之一。这仍然是结构化编程,而不是意大利面代码和
break
语句。实际上,我认为从这些解决方案中,带有
goto
的原始代码是最好的Vyktor,在将指针传递到
free
之前,不需要检查NULL。它保证忽略
NULL
指针。这不像10年前那样是真的,但现在这些检查没有意义了。@DyP对此表示感谢,但忘了放下它,补充道。在函数中清理并拥有一个退出点是goto完美的情况之一。这仍然是结构化编程,而不是意大利面代码。事实上,Gotos非常棒。好了,到处都是+1对于伟大的来源;)
goto
=
jmp
,您可以将C中的每个语言控件构造重写为goto:)+1。事实上,Gotos非常棒。好了,到处都是+1对于伟大的来源;)
goto
=
jmp
,您可以将C中的每个语言控件构造重写为goto:)