如何处理C中的错误?

时间:2017-04-22 04:05:32

标签: c error-handling

说,我有这样的代码:

int foo() {
    ...
    int buff_size;
    scanf("%d", &buff_size);
    FILE * fp = fopen("./file", "a+");
    char *buff = malloc(buff_size*sizeof(char));
    char *buff2 = malloc(buff_size*sizeof(char));
    char *buff3 = malloc(buff_size*sizeof(char));
    while (!feof(fp)) {
        /*do something, say read, write etc.*/
        if (/*error case 1*/) {
            free(buff);
            free(buff1);
            free(buff3);
            fclose(fp);
            return -1;
        }
        else if (/*error case 2*/) {
            free(buff);
            free(buff1);
            free(buff3);
            fclose(fp);
            return -2;
        }
        ...
        else if (/*error case k*/) {
            free(buff);
            free(buff1);
            free(buff3);
            fclose(fp);
            return -k;
        }
    }
    ...
    free(buff);
    free(buff1);
    free(buff2);
    fclose(fp);
    return 0;
    }

对于C不提供 try ... throw ... finally 语法,我必须关闭文件描述符和我在返回错误整数代码之前创建的空闲堆内存指针。它会产生一些重复的代码,使代码变得丑陋。

有谁知道我应该如何修改这种代码以使其看起来更简短?

2 个答案:

答案 0 :(得分:4)

您编写的代码等同于

    FILE * fp = fopen("./file", "a+");
    int return_value = 0;                  /*  assume zero means no error */
    char *buff = malloc(1024*sizeof(char));
    char *buff2 = malloc(1024*sizeof(char));
    char *buff3 = malloc(1024*sizeof(char));

    while (feof(fp))
    {
        /*do something, say read, write etc.*/
        if (/*error case 1*/)
        {
            return_value = -1;
        }
        else if (/*error case 2*/)
        {
            return_value = -2;
        }
        // ...
        else if (/*error case k*/)
        {
            return_value = -k;
        }
    }

    if (return_value == 0)   /* if no error has occurred, we can still do stuff  */
    {
        ...
    }

    /*   I have assumed all buffers need to be released 
         and files closed as the function returns
    */

    free(buff);
    free(buff1);     /*  you probably intend buff2 and buff3 here, to match the malloc() calls */
    free(buff2);
    fclose(fp);
    return return_value;
}
但是,我没有解决代码中的两个严重错误。你需要。

  • fopen()可能会失败,并返回NULL。如果是这样,将其传递给feof()fclose()会产生未定义的行为。您的代码根本没有检查,并且在调用feof()fclose()之前需要同时执行这两项操作。
  • while (!feof(fp)) {read_something_from(fp); use_something();}形式的循环是一个坏主意。有关详细信息,请查看Why is “while ( !feof (file) )” always wrong?

不太重要 - 对于固定大小的数组(在编译时固定大小),您可能不需要使用malloc(),这也意味着您不需要使用free()。但是,您仍然需要处理fopen()的潜在失败。

答案 1 :(得分:1)

对于这种具有常见清理代码的东西,我会使用返回值变量和goto

int foo() {
    ...
    // append extended mode ... what are you doing with this?
    FILE * fp = fopen("./file", "a+");
    char buff[1024];
    char buff2[1024];
    char buff3[1024];

    int ret = 0;

    while (/* file I/O is valid on fp */) {
        /*do something, say read, write etc.*/
        if (/*error case 1*/) {
            ret = -1;
            goto cleanup;
        }
        else if (/*error case 2*/) {
            ret = -2;
            goto cleanup;
        }
        ...
        else if (/*error case k*/) {
            ret = -k;
            goto cleanup;
        }
    }
    ...
cleanup:
    free(buff);
    free(buff2);
    free(buff3);
    fclose(fp);
    return ret;
}

这也可以防止必须复制粘贴代码或重新输入错误(如当前代码所示)。