检查大量返回值时的好c风格

有时候我必须编写代码来处理事务和检查错误条件(例如,调用库函数,检查其返回值,继续)。 这通常导致长期运行,其中实际工作发生在if语句的条件下,例如

if(! (data = (big_struct *) malloc(sizeof(*data)))){ //report allocation error } else if(init_big_struct(data)){ //handle initialization error } else ... 

你们是怎么写这种代码的? 我查了几个样式指南,但他们似乎更关心变量命名和空格。

风格指南的链接欢迎。

编辑:如果不清楚,我不满意这种风格的易读性,并寻找更好的东西。

虽然我很难说,但这可能是一个永不流行的goto 。 这是我在这个主题上找到的一个链接: http : //eli.thegreenplace.net/2009/04/27/using-goto-for-error-handling-in-c/

我通常以这种方式编写代码:

 data = (big_struct *) malloc(sizeof(*data)); if(!data){ //report allocation error return ...; } err = init_big_struct(data); if(err){ //handle initialization error return ...; } ... 

通过这种方式,我可以避免调用函数,因为您可以检查返回值,因此调试更容易。

不要在生产代码中使用assert
在调试模式下, assert永远不应该用于实际发生的事情(比如malloc返回NULL ),而应该在不可能的情况下使用(比如数组索引在C中超出范围)

阅读这篇文章了解更多。

我曾经使用的一种方法是W. Richard Stevens在Unix网络编程中使用的方法 (代码可以在这里下载。对于他希望一直成功的常见function,并且无法追求失败,他将它们包装起来,使用大写字母(垂直压缩的代码):

 void * Malloc(size_t size) { void *ptr; if ( (ptr = malloc(size)) == NULL) err_sys("malloc error"); return(ptr); } 

err_sys here显示错误,然后执行exit(1) 。 这样你就可以调用Malloc并知道如果出现问题就会出错。

UNP仍然是我认为作者有代码的唯一一本书,该代码检查所有可能失败的function的返回值。 其他每本书都说“你应该检查一下返回值,但我们会留下让你以后做的”。

我倾向于

  • 将错误检查委托给包装函数(如Stevens)
  • 出错时,使用longjmp模拟exception。 (我实际上使用Dave Hanson的C接口和实现来模拟exception。)

另一种选择是使用Don Knuth的文字编程来管理error handling代码或其他类型的预处理器。 只有在您为商店设置规则时,此选项才可用:-)

像这样的代码的唯一分组属性是,只需要遵循外部强加的序列。 这就是你将这些分配放在一个函数中的原因,但这是一个非常弱的共性。 为什么有些人建议放弃嵌套if的范围优势超出我的理解范围。 你正在有效地试图将口红放在猪身上(没有任何侮辱) – 代码的本质永远不会产生任何干净,你可以做的最好的事情是使用编译器帮助来捕获(维护)错误。 坚持使用if’s恕我直言。

PS:如果我还没说服你:如果你必须做出三元决定,那么goto-solution会是什么样子? if肯定会变得更加丑陋,但是goto的???