使用assert处理错误检查

我看了一遍,似乎有很多关于断言的混合观点。 例如,如果我是malloc的指针,并想确保它已正确分配,我会写:

p = malloc(sizeof(int)); assert(p) 

代替:

 p = malloc(sizeof(int)); if (p == NULL) { ... send error message } 

我知道断言它会终止程序,但出于测试目的 – 我想知道的是绝对最安全的方式:

  1. 测试像malloc正确完成的事情。
  2. 处理错误,如果某些东西不是正确的malloc

  1. 测试失败:
    如果无法向程序提供所请求的内存量,则C标准需要malloc函数返回NULL。

这意味着如果malloc的返回值为非NULL,则可以确保正确分配了所有内存。

检查NULL返回值是确定malloc是否成功的唯一方法。 如果断言失败, assert函数可用于停止程序,但在程序的生产版本中,必须有其他error handling。

  • 处理失败:
    如果返回值为NULL,请使用errno变量确定故障发生的原因。 errno变量也是C标准的一部分。
  • 对于LINUX,以下是errno可以设置为的值列表:

    http://www-numi.fnal.gov/offline_software/srt_public_context/WebDocs/Errors/unix_system_errors.html

  • 重要信息 :malloc故障是一个严重错误。 如果在程序执行中发生这种情况,请不要尝试继续在程序中执行其他function。 一旦记录错误并报告给程序用户,就停止(退出)程序,如下所示:

    您应该使用具有非零返回值exit函数来通知程序用户程序退出并显示错误状态。 exit函数也是C语言标准的一部分。

    此外,在退出程序之前,请确保已分配的所有其他内存(在malloc失败之前)已正确取消分配。

    召回assert()通常仅在程序的调试版本中有效,而不是发布版本。

    将潜在错误分类为组:

    1)必须处理的运行时错误。
    assert()在这里并不好,而代码必须处理错误。

    2)应该处理的运行时错误尚无定义的补救措施。
    assert()在这里也不明智。 代码应发出信号(保留错误信息)并退出。

    3)运行时错误,没有简单的重新处理它们。
    assert() 可以在这里使用。 现在当程序出现故障/死亡/挂起时,我们什么都没有。 如果可能的话,建议代码应该在#2中发出信号。

    4)编译时间错误。
    assert(sizeof(int)*CHAR_BIT >= 32)是一个很好的示例用法。 可以合理地假设构建将在调试模式下发生。 即使这会带来部署源代码的风险,该字段中的用户可能会跳过调试版本,因此建议仅对内部代码使用assert()

    assert()是C工具箱中的一个工具。 它有其用途和误用。


    使用malloc() ,我参与了许多禁止直接使用C lib malloc()的项目,而是使用了项目特定的代码,如my_malloc_never_fail()my_malloc_may_fail() ,它们具有error handling和指标。 正如@Weather Vane评论的那样,良好的error handling具有挑战性。