检查返回int的函数时出错

如果我有一个返回某种指针的函数,我会通过设置错误时返回NULL来检查错误。

char *foo(void) { //If stuff doesn't go okay return NULL; } char *bar = foo(); if(!bar) return 1; 

这很有效,因为我知道在这种情况下我永远不会想要返回NULL。

但是,有时我会有返回整数的函数(在这种情况下,我从配置文件中读取int)。 但是,问题是现在无法检查返回的值是否有错误,因为任何值(包括0)都可能是真的。

几个解决方法:

  1. 在函数中包含错误代码参数
  2. 返回错误代码并包含int指针作为参数

这两个问题都是我有一组函数,它们都做同样的事情,但对于不同的类型,我想维护一个常规的接口,以便它们可以以相同的方式使用。

是否有其他解决方案不涉及更改function的接口? 处理这种情况最常见的方法是什么?

选择解决方案

感谢您对此的所有想法和答案。

最后我决定,如果函数旨在返回一些数据,则只能通过error参数返回错误。 否则,将直接返回错误。

我选择了这个根,因为通常我发现当返回更复杂的数据forms时,潜在错误的数量几乎总是大于1.这意味着使用NULL作为错误数据的唯一来源是不切实际的,因为它意味着没有确定错误实际是什么的方法。 对于将数据作为int返回的函数,也不可能将多个不同的错误代码与有效数据区分开来。

当然,对于没有真正返回任何数据的函数,情况也是如此,在这种情况下,我可以自由地将返回值用作错误代码。

我也喜欢上述模式明确区分返回数据的函数和不返回数据的函数。

有一个全局变量的可怕解决方案 – 类似于errno 。 不建议。

您可以使用函数从上次调用集合中的某个函数中检索错误条件 – 不建议再次使用。 这不是线程安全的,并且您可能会跨函数共享错误 – 而不是能够从您使用的函数中查询最后一个错误(尽管可以通过适当的设计来修复)。

您可能会决定所有函数都返回一个可测试的状态,并通过指针参数返回该值。 这使您可以在所有function中保持一致性,并改变使用模式。 你会一直写:

 if ((rc = your_function(in1, in2, &out)) != 0) ...handle error... else ...use returned value... 

这可能是最不讨厌的解决方案。

将指针传递给错误结构或指向错误结构指针的另一个主要选择是容易导致资源管理问题。 如果错误结构是固定大小,则可以使其工作,从而消除资源管理问题。

 Error_t err; int result = your_function(in1, in2, &err); if (err.code != 0) ...handle error... else ...use returned value... 

您无法在调用函数的同一行中测试错误条件,有些人会认为这是一种麻烦。 当你处于一系列操作的第三个’else if’子句时,它最重要 – 然后你必须引入一个新级别的嵌套,其中错误代码作为返回值不需要。 对它有利的是,错误结构中的信息可以比单个错误号更全面,这可能导致更好的诊断。

您可以使用混合解决方案 – 错误返回代码和错误参数,以包含用于改进诊断的额外信息。 但是,很少选择AFAIK。

最好和最常见的方式(例如,由Windows API实现)是编写所有error handling,如下所示:

int func(Error_t * error);

其中Error_t是某种错误指示。 这样,它不会干扰返回的结果。

您可以牺牲INT的最大负数或正数,例如INT_MAX。 只需创建一个const MY_INT_ERROR_VALUE并与之进行比较即可。

有几种方法可以做你想要的,但是所有这些方法都会让你有一个非同构的界面(或者列表是一种非同类的方法来测试错误)。

如果您无法更改函数的签名,则可以使用函数在发生错误时设置的全局变量,但我认为此解决方案比更改界面更脏。

另一个解决方案可能是使用跳转或系统信号模拟exception,但我仍然不建议(这也不是可移植的)。

这个怎么样:

 void *foo(void *res) { // cast the void *res to whatever type the result would be if (/* successfull */) return res; /* error */ return NULL; } 

这样,您将拥有所有这些function的相同签名,并且您还可以轻松检查错误。

在使用缺少exception处理的语言编写代码时,我的偏好是始终使用返回值作为错误指示符。

 int get_value(int *value) { if ( input_ok ) *value = input; return 0; return -1; } 

这似乎不实用,因为它强制你使用中间变量来存储函数结果,但它被certificate是有用的很多次来捕获错误并正确处理它们(你永远不能依赖用户输入)。

此外,您应该注意,使用特殊值来显示错误并不是一个好主意:您永远不知道代码会发生什么。 如果以后要添加新function,不幸的是特殊值对此function有用,您会怎么做? 用另一个特殊错误值写一个新函数? 如果输入应覆盖整个返回类型范围怎么办? 如果这是一个更大的项目的一部分,你怎么能确保每个可能使用你的function的程序员都知道特殊的价值?

安全方面更错误:不要使用特殊值并使用专用的error handling路径。

请注意,您可以反转上面的代码并写入int get_value(int *error);

1.使用NaN,如浮动协处理器。 选择一个可能从未用作结果的值来指示错误。

 # define VALUE_OF_FAIL (-99999) 

那么:

 char foo(void) { // If stuff doesn't go okay return VALUE_OF_FAIL; } char bar = foo(); if (bar == VALUE_OF_FAIL) return 1; 

同样,您必须保证常规计算的结果永远不会是VALUE_OF_FAIL。 从整数范围的外围选择一个数字。 您可以定义更多失败代码,但是您应该编写一个函数来检查变量是否失败。

2.将计算代码组织到类中,然后添加isValid()方法:

 class FooBar { public FooBar() { // constructor this.fail = false; // initialize here... } char foo(void) { // the computation method this.fail = false; // ...or here // If stuff doesn't go okay this.fail = true; // or error code return 0; // any value } bool failed() { return this.fail; } } // outside the class fb = new FooBar(); char bar = fb->foo(); if (fb->failed()) return 1;