如何处理C语言中不断的错误检查?

How to deal with constant error checking in C?

提问人:Gabriel Silva Schilive 提问时间:4/19/2023 最后编辑:Gabriel Silva Schilive 更新时间:4/19/2023 访问量:76

问:

在 C 语言中,我调用了许多函数,必须检查它们是否有效。因此,代码变得 ~3 倍!举个例子:

char *myStr = malloc(sizeof(char));
if (!myStr)
    return NULL;

有没有一种更易读的方法来在 C 语言中进行代码调用和错误检查?或者这就是饼干碎裂的方式?

我尝试了以下宏。但它在 C 语言中似乎不是惯用的,也没有奏效——这个错误是由“Key Y-N”指出的。

#define TRY_EXCEPT(try_statement, except_condition, except_statement) try_statement##if(except_condition){except_statement}

编辑:这是我的意思是调用和错误检查的密度。

if (!varNames)
    goto exit_fail;

struct dynStr *asmCode = dynStr_create();
if (!asmCode)
    goto exit_fail;

int rc;
rc = dynStr_append(asmCode, ".data\n");
if (!rc)
    goto exit_fail;

char *varName;
for (size_t i = 0; (varName = daStr_getString(varNames, i)); i++) {
    rc = dynStr_append(asmCode, "DD ");
    if (!rc)
        goto free_and_exit;

    rc = dynStr_append(asmCode, varName);
    if (!rc)
        goto free_and_exit;

    rc = dynStr_append(asmCode, "\n");
    if (!rc)
        goto free_and_exit;
}
c 错误处理 可读性

评论

0赞 Samuel Liew 4/19/2023
评论已移至聊天室;请不要在这里继续讨论。在在此下方发表评论之前,请查看评论的目的。不要求澄清或提出改进建议的评论通常属于 Meta Stack Overflow 或 Stack Overflow Chat 中的答案。继续讨论的评论可能会被删除。

答:

0赞 Harith 4/19/2023 #1

我会这样浓缩它:

if (!(rc = dynStr_append(asmCode, "DD ")) 
    || !(rc = dynStr_append(asmCode, varName)) 
    || !(rc = dynStr_append(asmCode, "\n"))) {
    goto free_and_exit;
}

或者使用另一个变量:

int exit_stat = !(rc = dynStr_append(asmCode, "DD ")) 
                || !(rc = dynStr_append(asmCode, varName)) 
                || !(rc = dynStr_append(asmCode, "\n"));

if (exit_stat) {
    goto free_and_exit;
}

或者干脆删除对以下各项的赋值:rc

if (!dynStr_append(asmCode, "DD ")) 
    || !dynStr_append(asmCode, varName) 
    || !dynStr_append(asmCode, "\n"))) {
    goto free_and_exit;
}

评论

0赞 Gabriel Silva Schilive 4/19/2023
没想到这样的“布尔”变量!我确实想过最后一个例子,但我担心它很糟糕,就像太杂乱了一样。但在这里似乎不错。谢谢你提供这么多选择!
0赞 Andrew Henle 4/19/2023
或者干脆删除对 rc 的赋值如果你没有把它放在那里,我会非常想投反对票——把赋值放到 if 语句中已经足够容易出错了。将多个赋值塞进一个复杂的 if 语句中实际上是在乞求错误。
0赞 Harith 4/19/2023
@AndrewHenle 是的,它看起来很丑陋。但是 OP 有一个任务在循环中,所以我就去做了。for
0赞 Fe2O3 4/19/2023 #2

您可以通过认识到 LF 不是那么特别来节省成本。(并且,请注意在假定的动态分配之后分支的位置。

struct dynStr *asmCode = dynStr_create();
if (!asmCode)
    goto exit_fail;

if( !dynStr_append(asmCode, ".data") )
    goto free_and_exit; // memory leak fixed...

char *varName;
for( size_t i = 0; (varName = daStr_getString(varNames, i)); i++ ) {
    if( !dynStr_append(asmCode, "\nDD ") // Notice the LF prepended
    ||  !dynStr_append(asmCode, varName) )
        goto free_and_exit;
}
if( !dynStr_append(asmCode, "\n") )
    goto free_and_exit;

评论

0赞 Gabriel Silva Schilive 4/19/2023
感谢您的回答!这个想法很漂亮,我已经在 Linux 内核中看到了它,这意味着我可以责怪其他人。我喜欢。但我为我的无知感到抱歉:什么是LF?顺便说一句,对不起,漏水了......
0赞 Fe2O3 4/19/2023
LF== “换行”,又名。“换行符”...建议你学习ASCII字符的常规名称...