在生产环境中捕获返回代码?

时间:2009-04-01 06:19:00

标签: c error-handling return-value

我想知道是否检查我们为生产环境编写的所有函数的返回码。 对于e,g,我经常使用C并且你也会捕获标准库的返回码,而不仅仅是你编写的函数,还有第三方API /标准库/任何其他库。

我在制作中看到的大多数代码都没有这样做。 所以我的问题是那些在生产环境中工作并且已经编写了大约20年左右的生产代码的有经验的人。 您是否从第三方API /标准库/任何其他库中获取返回代码,而不仅仅是您实现的函数? 只是为了说明我的意思 你是否抓住C标准库的C标准lib函数(snprintf / sprintf,strncat / strcat等等,...)的返回码。

感谢您的所有回复。

6 个答案:

答案 0 :(得分:3)

我认为你不应该对此采取全有或全无的方法。当期望函数调用出现问题时捕获返回/错误代码(当然,如果后续计算取决于函数返回的内容)。但是,如果您非常确定该调用不会导致错误(或者您甚至没有使用返回值),执行跳过捕获返回值。

这是个人工程判断的一个领域,而不是某些规定的“最佳实践”。此外,我认为同样的想法将适用于异常处理。

答案 1 :(得分:3)

我花了很长时间才学到这一点,但除了少数例外,您应该始终检查函数的返回代码。

我已经看到太多调用malloc的代码(例如)并且只是愉快地使用它返回的指针。 99.9%的时间,这不是问题,但偶尔malloc将失败,并且当您尝试取消引用NULL指针时程序将崩溃。现在,有人可能会争辩说,如果malloc仍然返回NULL,你想要退出 - 这可能是真的,但你应该努力优雅地退出,即使是致命的错误。

所以,是的:检查返回代码。不要假设某些东西只是因为它总是在过去起作用。事情总是失败通过防御性编码,检查错误,检查errno,输出strerror并优雅地失败,您将节省大量时间和悲伤。

答案 2 :(得分:2)

如果函数可能返回错误代码 - 请务必检查并处理它,就像这样简单。这个规则可以在寻找漏洞时节省大量时间。

如果函数总是返回无法指示错误的代码而您不需要结果(例如printf),那么您可以忽略它。

答案 3 :(得分:2)

是的,除非极少数例外,您的程序应始终检查并处理错误返回值,即使(特别是)您不希望出现任何错误。毕竟,我们软件的环境通常不如我们希望的那样可靠。

在本质上,这就是大多数现代语言都有例外的原因:除其他外,它们为您未明确处理(即捕获)的错误提供“默认错误处理程序”(中止和堆栈跟踪)。它们还允许集中错误处理,而不是检查每个函数调用的返回值。

答案 4 :(得分:1)

如果函数返回错误代码,则调用代码应该决定如何处理错误。对于某些程序,忽略错误可能没问题;例如,当写入stderr时,这往往是人们对标准I / O库中的错误所做的事情。 (如果消息失败,你能做什么?退出?你还在做什么吗?)

一个令人讨厌的来源是记录为返回值但始终返回相同值(通常为0)的函数。通常,这些是在void返回之前最初用K& R C编写的函数。它们已转换为int,然后添加了“return(0);”以平息有关“函数不返回值”的警告,而不是将其转换为void。这些职能应修改为void;在过渡期间,可以忽略它们的错误返回值。

我不同意另一个答案中的观察结果“当您预期函数调用出现问题时捕获返回/错误代码”。问题正是出乎意料的是杀死了你。即使最稳定的操作也可能意外失败(可能是DBMS崩溃了,所以即使你有连接,也不再有了),而且你的软件必须识别并处理这些问题。

答案 5 :(得分:0)

snprintf很有用,因为您可能想要分配更大的缓冲区然后重试,或者您可能按顺序调用它:

// cons lists as [a,b,c, ...]
if ( type == kin_cons_class() ) {
    size_t offs = snprintf ( buf, max, "[" );

    if ( offs >= max )
        return nul_terminate ( buf, offs, max );

    size_t count = depth;

    kin_cons_ref_t empty = kin_cons_nil();
    kin_cons_ref_t cons;

    for ( cons = ref; cons != empty; cons = kin_cons_tail ( cons ) ) {
        if ( count > 15 ) {
            offs += snprintf ( buf + offs, max - offs, ", ..." );

            break;
        }

        if ( cons != ref ) {
            offs += snprintf ( buf + offs, max - offs, "," );

            if ( offs >= max )
                return nul_terminate ( buf, offs, max );
        }

        offs += string_repr ( buf + offs, max - offs, kin_cons_head ( cons ), depth, escape_strings );

        if ( offs >= max )
            return nul_terminate ( buf, offs, max );

        ++count;
    }

    if ( offs >= max )
        return nul_terminate ( buf, offs, max );

    offs += snprintf ( buf + offs, max - offs, "]" );

    return nul_terminate ( buf, offs, max );
}

如果你继续进行所有的offs >= max测试,就会出现缓冲区溢出,并且会出现段错误。

printf不会发生这种情况,因此检查返回时不太常见。

如果您需要根据功能是否有效来改变行为,请检查返回。许多标准库函数可能会失败,或者稍后会导致未定义的行为,因此您需要检查这些返回。

如果您不需要根据返回值更改行为,那么检查它是没有意义的。