C库中的错误报告

nc3*_*c3b 20 c design-patterns error-reporting

我正在寻找一种报告C库中错误的可靠方法.考虑一个简单的队列示例:

struct queue *q = malloc(sizeof(*q));
if (NULL == q) {
    /* malloc failed. now what ? */
    return NULL; /* maybe ? */
}
Run Code Online (Sandbox Code Playgroud)

好的,所以对于那个示例,返回NULL不是有效的,所以返回它以指示错误是有意义的.但

void *get_data()
{
    /* stuff */

    /* Error detected. NULL is a valid return, now what ? */

    /* stuff */
}
Run Code Online (Sandbox Code Playgroud)

更重要的是,一旦我们发出错误信号,如何信号什么是错误?我已经考虑过了,并没有一个令人满意的解决方案.

  • 使用errno或其他一些全局对象不是我想做的事情(也许这些函数可以从多个线程调用等).

  • 我想让客户端提供一些可以在调用后检查的"状态"对象,但这会使API变得非常难看.

那么你对这个主题的看法是什么?你如何以干净的方式报告错误?

Spa*_*rky 6

我有几个建议.

建议#1 - 使用自定义errnos.我知道你表示你不愿意使用它.我知道你担心errno会在多线程环境中被破坏,但我希望每个线程都有自己的errno存储空间.以下链接http://compute.cnr.berkeley.edu/cgi-bin/man-cgi?errno+3表明它很容易做到.

就构造自定义errno而言,您总是可以将errno分成两部分...模块编号和模块错误代码.

eg.
#define MODULE_NAME_error_code ((MODULE_NUMBER << 16) | (error_code))
Run Code Online (Sandbox Code Playgroud)

如果库中检测到错误,则可以将errno设置为所需的值.如果有多个模块,则可以帮助识别问题区域.当然,如果您的库要与使用此方法的其他人一起使用,则需要某种形式的自定义errno同步.

建议#2 - 让你的例程在成功时返回0并返回一个自定义的非零值,并让其中一个参数成为你想要设置的值的指针.可以轻松检测到错误; 但是,如果你有使用这种方法的深度调用树,那么记录它们可能会很麻烦.

希望这可以帮助.


Ran*_*832 6

int get_data(void **ptr)
Run Code Online (Sandbox Code Playgroud)

如果没有明显的"错误返回",那么您的输出值可能不应该是返回值.错误可能是错误,一些其他自定义详细错误值(*cough*HRESULT),如果函数成功则只是true/false,或者其他一些有用信息(数据长度,如果错误则为-1) )