使用assert处理错误检查
我看了一遍,似乎有很多关于断言的混合观点。 例如,如果我是malloc的指针,并想确保它已正确分配,我会写:
p = malloc(sizeof(int)); assert(p)
代替:
p = malloc(sizeof(int)); if (p == NULL) { ... send error message }
我知道断言它会终止程序,但出于测试目的 – 我想知道的是绝对最安全的方式:
- 测试像
malloc
正确完成的事情。 - 处理错误,如果某些东西不是正确的
malloc
。
- 测试失败:
如果无法向程序提供所请求的内存量,则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具有挑战性。