检查返回int的函数时出错

Rup*_*ott 7 c error-handling

如果我有一个返回某种指针的函数,我会在错误时将返回值设置为NULL来检查错误.

char *foo(void) {
  //If stuff doesn't go okay
  return NULL;
}

char *bar = foo();
if(!bar) return 1;
Run Code Online (Sandbox Code Playgroud)

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

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

一些解决方法:

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

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

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

选择解决方案

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

最后我决定,如果函数是为了返回某些数据,则只能通过error参数返回错误.否则,将直接返回错误.

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

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

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

Jon*_*ler 4

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

您可以使用函数来检索上次调用集合中函数​​之一的错误条件 - 再次强调,不推荐。这不是线程安全的,并且您可能会在函数之间共享错误 - 而不是能够从您使用的函数中询问最后一个错误(尽管这可以通过适当的设计来修复)。

您可能决定所有函数都返回可测试的状态,并且该值通过指针参数返回。这使您可以在使用模式发生变化的情况下实现所有功能的一致性。你会一直这样写:

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

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

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

Error_t err;

int result = your_function(in1, in2, &err);
if (err.code != 0)
    ...handle error...
else
    ...use returned value...
Run Code Online (Sandbox Code Playgroud)

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

您可以使用混合解决方案 - 错误返回代码加上错误参数来包含改进诊断的额外信息。不过,据我所知,它很少被选择。