使用断言处理错误检查
Handling error checking with assert
我看了一圈,似乎对assert的看法褒贬不一。例如,如果我正在 malloc'ing 一个指针并想确保它被正确分配,我会写:
p = malloc(sizeof(int));
assert(p)
而不是:
p = malloc(sizeof(int));
if (p == NULL)
{
... send error message
}
我知道使用 assert 会结束程序,但出于测试目的 — 我想知道的是绝对最安全的方法:
- 正在测试
malloc
之类的事情是否正确完成。
- 如果某事
malloc
不正确,则处理错误。
Recall assert()
通常仅在程序的 debug 版本中有效,在 release 版本中无效。
将潜在错误分组:
1) 运行-必须处理的时间错误。
assert()
在这里不好,代码必须处理错误。
2) 运行- 应该处理但没有明确补救措施的时间错误。
assert()
在这里也不明智。代码应发出信号(留下错误消息)并退出。
3) 运行-time 错误,没有简单的方法来处理它们。
assert()
可以用在这里。现在当程序 faults/dies/hangs 我们什么都没有了。如果可能的话,推荐代码应该像#2 中那样发出信号。
4) 编译时错误。
assert(sizeof(int)*CHAR_BIT >= 32)
是一个很好的示例用法。假设构建将在调试模式下进行是合理的。即使这会带来部署源代码的风险,现场用户可能会跳过调试版本,因此建议仅对内部代码使用 assert()
。
assert()
是C工具箱中的一个工具。它有其用途和误用。
使用 malloc()
,我从事过许多禁止直接使用 C 库 malloc()
的项目,而是使用项目特定代码,如 my_malloc_never_fail()
和 my_malloc_may_fail()
有错误处理和指标。正如 评论的那样,良好的错误处理具有挑战性。
- 测试失败:
如果无法为程序提供所请求的内存量,则 C 标准要求 malloc 函数 return NULL。
也就是说,如果malloc的return值为非NULL,那么可以确定ALL的内存被正确分配了。
检查 NULL return 值是确定 malloc 是否成功的唯一方法。 assert
函数可用于在断言失败时停止程序,但在程序的生产版本中,
必须有其他错误处理。
- 处理失败:
如果 return 值为 NULL,请使用 errno
变量确定失败发生的原因。 errno
变量也是 C 标准的一部分。
对于 LINUX,这里是值列表 errno
可以设置为:
http://www-numi.fnal.gov/offline_software/srt_public_context/WebDocs/Errors/unix_system_errors.html
-
重要提示:malloc 失败是一个严重的错误。如果这发生在
程序执行,不要试图继续执行额外的
程序中的功能。
记录错误后立即停止(退出)程序并
报告给程序的用户,如下:
您应该使用具有 非零 return 的 exit
函数
value 通知程序用户程序退出
带有错误状态。 exit
函数也是
C语言标准的一部分。
此外,在退出程序之前,请确保所有其他内存
已分配(在 malloc 失败之前)已正确取消分配。
我看了一圈,似乎对assert的看法褒贬不一。例如,如果我正在 malloc'ing 一个指针并想确保它被正确分配,我会写:
p = malloc(sizeof(int));
assert(p)
而不是:
p = malloc(sizeof(int));
if (p == NULL)
{
... send error message
}
我知道使用 assert 会结束程序,但出于测试目的 — 我想知道的是绝对最安全的方法:
- 正在测试
malloc
之类的事情是否正确完成。 - 如果某事
malloc
不正确,则处理错误。
Recall assert()
通常仅在程序的 debug 版本中有效,在 release 版本中无效。
将潜在错误分组:
1) 运行-必须处理的时间错误。
assert()
在这里不好,代码必须处理错误。
2) 运行- 应该处理但没有明确补救措施的时间错误。
assert()
在这里也不明智。代码应发出信号(留下错误消息)并退出。
3) 运行-time 错误,没有简单的方法来处理它们。
assert()
可以用在这里。现在当程序 faults/dies/hangs 我们什么都没有了。如果可能的话,推荐代码应该像#2 中那样发出信号。
4) 编译时错误。
assert(sizeof(int)*CHAR_BIT >= 32)
是一个很好的示例用法。假设构建将在调试模式下进行是合理的。即使这会带来部署源代码的风险,现场用户可能会跳过调试版本,因此建议仅对内部代码使用 assert()
。
assert()
是C工具箱中的一个工具。它有其用途和误用。
使用 malloc()
,我从事过许多禁止直接使用 C 库 malloc()
的项目,而是使用项目特定代码,如 my_malloc_never_fail()
和 my_malloc_may_fail()
有错误处理和指标。正如
- 测试失败:
如果无法为程序提供所请求的内存量,则 C 标准要求 malloc 函数 return NULL。也就是说,如果malloc的return值为非NULL,那么可以确定ALL的内存被正确分配了。
检查 NULL return 值是确定 malloc 是否成功的唯一方法。
assert
函数可用于在断言失败时停止程序,但在程序的生产版本中, 必须有其他错误处理。 - 处理失败:
如果 return 值为 NULL,请使用errno
变量确定失败发生的原因。errno
变量也是 C 标准的一部分。对于 LINUX,这里是值列表
errno
可以设置为:http://www-numi.fnal.gov/offline_software/srt_public_context/WebDocs/Errors/unix_system_errors.html
-
重要提示:malloc 失败是一个严重的错误。如果这发生在 程序执行,不要试图继续执行额外的 程序中的功能。 记录错误后立即停止(退出)程序并 报告给程序的用户,如下:
您应该使用具有 非零 return 的
exit
函数 value 通知程序用户程序退出 带有错误状态。exit
函数也是 C语言标准的一部分。此外,在退出程序之前,请确保所有其他内存 已分配(在 malloc 失败之前)已正确取消分配。