【问题标题】:Common C idiom for keeping track of where errors occur用于跟踪错误发生位置的常见 C 习惯用法
【发布时间】:2011-11-19 21:04:08
【问题描述】:

我有一个任务,我需要从文件中读取一定数量的Foos。如果文件中的数据对于Foos 之一的格式不正确,有哪些常见的方式来指示(例如,stderr)应该更正Foos 中的哪一个?

我的代码如下所示:

Foo foos[50];
FILE *file = fopen(...);
int i;

for (i = 0; i < sizeof(foos); ++i)
{
    if (readFoo(&foos[i], file) != 1)
        break;
} 

如果读取成功,readFoo 函数将返回1;如果不是,它会返回一个负数并向stderr 打印一个错误,它指定出了什么问题,但没有说明错误在哪里。我应该如何实现这个(干净),以便我也告诉用户i 的值?

在 C++ 中,我会在例外情况下执行此操作。在 C 语言中,我想过做这样的事情(readFoo 会在出现问题时相应地设置error):

/* These go in a source file */
const char *error = NULL;
const char error1[] = "Error 1 occurred.";
const char error2[] = "Error 2 occurred."; 

const char *getLastError() {
    return error;
}

还有什么其他方法可以解决这个问题?

【问题讨论】:

    标签: c error-handling


    【解决方案1】:

    执行此操作的“干净”方法是在调用站点进行错误报告。也就是说,执行以下操作:

    if( readFoo( foos + i, 文件, errbuf, errbuf_size ) != 1 ) { fprintf(stderr, "%d: %s\n", i, errbuf); ... }

    也就是说,readFoo 使用错误消息填充缓冲区,而不是将其写入 stderr。

    【讨论】:

      【解决方案2】:

      类 Unix 操作系统中的一个众所周知的习惯用法是 errno(3),其中系统调用将在错误时返回 -1 并设置全局变量以指定特定的错误类型。由于这不能很好地与多线程配合使用,因此将 errno 定义为对检索每个线程错误代码的函数的调用颠覆了最初的想法。

      然后,POSIX threads API 以另一种方式返回成功时返回零,失败时返回错误代码。在我看来,这是用户级代码错误报告的首选方式,我建议遵循此方式。

      【讨论】:

        【解决方案3】:

        标准 C 提供errno 来区分错误。如果你愿意,你也可以这样做。不过,看起来您已经有一个循环并且知道i 是什么。你不能这样做吗:

        if (readFoo(&foos[i], file) != 1) {
            fprintf(stderr, "Read error on foo #%d\n", i);
            break;
        }
        

        【讨论】:

        • 当然可以,但我希望消息看起来像“Foo #2: Incorrect value”,而不是“Incorrect value (Foo #2)”。 :) (readFoo 将在我打印 i 的值之前打印消息的描述。)
        • 您需要修改 readFoo 才能做到这一点。如果这是一个可接受的选项,您可以将其传递给i,将i 存储在readFoo 可以看到的全局变量中,或者在readFoo 中保留一个静态变量来计算它被调用的次数。
        • 这不太理想; readFoo 应该关心我正在阅读多个Foos。 :)
        • 好吧,如果您只是将readFoo 更改为不打印任何内容,您可以在调用者中执行所有错误打印。您甚至可以使用perror(3) 自动将errno 转换为人类可读的字符串。
        猜你喜欢
        • 2013-01-02
        • 1970-01-01
        • 2019-05-02
        • 2011-01-31
        • 2016-07-01
        • 2013-06-19
        • 1970-01-01
        • 2011-05-06
        • 1970-01-01
        相关资源
        最近更新 更多