C 库中的错误报告

发布于 2024-11-18 05:13:31 字数 644 浏览 3 评论 0原文

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

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

好的,对于该示例,返回 NULL 无效,因此返回它来发出错误信号是有意义的。但

void *get_data()
{
    /* stuff */

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

    /* stuff */
}

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

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

  • 我想过让客户供货 一些“状态”对象可以是 打电话后进行了检查,但是 会使 API 变得非常难看。

那么您对这个问题有何看法?如何以干净的方式报告错误?

I am looking for a robust way to report errors in a C library. Consider the simple example of a queue:

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

Okay, so for that example returning NULL isn't otherwise valid so it makes sense to return it to signal an error. But

void *get_data()
{
    /* stuff */

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

    /* stuff */
}

What's more, once we signal an error, how to signal what is the error ? I have thought about it and don't have a satisfying solution.

  • Using errno or some other global object isn't
    something I would like to do (perhaps
    the functions may be called from
    multiple threads etc).

  • I thought of making the client supply
    some "status" object that can be
    inspected after the call, but that
    would make the API quite ugly.

So what's your take on the subject ? How do you report errors in a clean way ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

习ぎ惯性依靠 2024-11-25 05:13:31
int get_data(void **ptr)

如果没有明显的“错误返回”,那么也许您的输出值不应该是返回值。错误可能是 errno、其他一些自定义的详细错误值 (*咳嗽* HRESULT)、函数成功时的 true/false,或者其他一些有用的信息(数据的长度,如果出现错误则为 -1) )

int get_data(void **ptr)

If there are no obvious 'error returns', then maybe your output value should not be the return value. The error could either be an errno, some other custom detailed error value (*cough* HRESULT), just true/false for if the function succeeded, or some other bit of useful information (the length of the data, or -1 if error)

爱你是孤单的心事 2024-11-25 05:13:31

我有几个建议。

建议#1——使用自定义错误号。
我知道您表示您不想使用它。我了解到您担心 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))

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

建议#2 -- 让您的例程在成功时返回 0,并在返回时返回自定义非零值,并让其中一个参数成为指向您要设置的值的指针。容易发现错误;但是,如果您有使用此方法的深层调用树,则记录它们可能会很麻烦。

希望这有帮助。

I have a couple of suggestions.

Suggestion #1 -- Use custom errnos.
I know that you indicated that you would prefer not to use that. I gather that you are concerned that errno will be clobbered in a multi-threaded environment, but I would expect that each thread should have its own storage for errno. The following link http://compute.cnr.berkeley.edu/cgi-bin/man-cgi?errno+3 suggests that it is rather easy to do.

As far as structuring the custom errno's, you can always divide the errno up into two portions ... a module number and an module error code.

eg.
#define MODULE_NAME_error_code ((MODULE_NUMBER << 16) | (error_code))

In case of detected errors in your library, you can then set the errno to a desired value. If there are multiple modules, it can help identify the problem area. Of course, if your library is to be used with others that use this method, then some form of synchronization of custom errno's is required.

Suggestion #2 -- Let your routines return 0 on success with a custom non-zero value on return and let one of the parameters be a pointer to the value you want to set. Errors can be detected easily; however documenting them may be troublesome if you have deep call trees that use this methodology.

Hope this helps.

丶视觉 2024-11-25 05:13:31

如果您确实想要一种多线程、可重入的方式来报告错误,我认为您无法在每次 lib 调用中逃避将指针传递给“status” struct 。该结构将包含其他对象状态内容,即相关调用的结果。

确实很丑,但不一定是坏事。

If you really want a multithreaded, reentrant, way to report errors, I think you cannot escape, in every lib call, to pass a pointer to a "status" struct . That struct would have among other object state stuff, the result of the call in question.

It's ugly indeed, but not necessarily bad.

葬心 2024-11-25 05:13:31

将“状态”参数作为指针传递可能看起来有点难看,但在 C 编程中是可以接受的,因为该语言中不存在更高级别的错误报告工具。

状态变量中的每个位都代表不同的错误,因此如果返回 NULL,调用者将必须测试状态和状态是否正确。 ERR_NOMEM 或 status & ERR_IO 等。错误掩码可以定义如下:

#define ERR_NOMEM (1 << 0)
#define ERR_IO    (1 << 1)
...

在函数内部设置适当的错误可以通过 status |= ERR_IO 来完成。

有时,这甚至可以让您灵活地指示多个错误 - 调用者可以检查状态和状态。 (ERR_NOMEM | ERR_IO) 以测试是否发生任何错误。

Having a "status" argument passed as a pointer may seem a bit ugly, but is accepted in C programming since higher-level error reporting facilities do not exist in the language.

Each bit in the status variable would represent a different error, so if NULL is returned, the caller will have to test whether status & ERR_NOMEM or status & ERR_IO, etc. The error masks can be defined as follows:

#define ERR_NOMEM (1 << 0)
#define ERR_IO    (1 << 1)
...

Setting the appropriate error inside the functions could be done as status |= ERR_IO.

This even gives you the flexibility to indicate more than one error sometimes - the caller can check status & (ERR_NOMEM | ERR_IO) to test whether any of the errors have occurred.

捎一片雪花 2024-11-25 05:13:31

我的第一个想法:为什么不使用 stderr,用指示问题来源和原因的消息填充它?或者,也许我错过了你的意图:)

My first thought: why not use stderr, filling it with messages indicating source and cause of the problem? Or, maybe I missed your intention :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文