使用断言处理错误检查

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 会结束程序,但出于测试目的 — 我想知道的是绝对最安全的方法:

  1. 正在测试 malloc 之类的事情是否正确完成。
  2. 如果某事 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()有错误处理和指标。正如 评论的那样,良好的错误处理具有挑战性。

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

    也就是说,如果malloc的return值为非NULL,那么可以确定ALL的内存被正确分配了。

    检查 NULL return 值是确定 malloc 是否成功的唯一方法。 assert 函数可用于在断言失败时停止程序,但在程序的生产版本中, 必须有其他错误处理。

  2. 处理失败:
    如果 return 值为 NULL,请使用 errno 变量确定失败发生的原因。 errno 变量也是 C 标准的一部分。

    对于 LINUX,这里是值列表 errno 可以设置为:

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

  3. 重要提示:malloc 失败是一个严重的错误。如果这发生在 程序执行,不要试图继续执行额外的 程序中的功能。 记录错误后立即停止(退出)程序并 报告给程序的用户,如下:

    您应该使用具有 非零 return 的 exit 函数 value 通知程序用户程序退出 带有错误状态。 exit 函数也是 C语言标准的一部分。

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