【问题标题】:When should assert() be used?什么时候应该使用 assert()?
【发布时间】:2021-03-24 22:16:05
【问题描述】:

在与许多开发人员一起开发大型 C++ 编程项目时,我们遇到了在代码中不当使用 assert() 的问题,这会导致确实发生断言并导致产品崩溃的质量差。

问题是正确使用 assert() 的好的原则是什么?什么时候使用 assert() 合适,什么时候不合适?是否有一个标准列表,每个断言都应该通过才能合法?我们如何鼓励正确使用 assert()?

作为第一次破解,我想说 assert() 应该只用于记录一个被认为不可能达到的条件,并且应该在运行时将其标识为 assert() 失败出现是因为违反了编程假设。

人们可以做得比这更好吗?你对 assert() 有什么体验?

【问题讨论】:

  • 当您知道必须满足某些条件才能使代码被视为“良好”时,请使用断言。如果断言失败,那么根据定义,代码必须被修复。
  • @Robert:同意+1,但必须考虑如果断言触发使程序崩溃,用户将损失多少工作。当浏览器丢失一组打开的标签时很烦人,但通常不是灾难;如果文字处理器因为断言而失去一天的工作,那将是一场灾难。困难的部分是 (a) 确定执行任何操作是否安全,以及 (b) 将系统保持在出现问题时可以恢复的状态。
  • 一个整天没有保存工作的人会在断言发生时得到他应得的。

标签: c++ assert


【解决方案1】:

对来自外部(方法外部或程序外部)的错误条件使用Exceptions,例如参数检查和缺失/缺陷外部资源,如文件或连接或用户输入。

使用断言来指示内部缺陷,例如编程错误、不应该发生的情况,例如类/方法不变量和无效的程序状态。

【讨论】:

    【解决方案2】:

    你应该使用 assert 来检查所有不应该发生的情况:

    • 输入参数的前提条件
    • 中间计算结果
    • 对象状态的后置条件

    但您应该仅在调试版本中或在明确激活发布时包含这些断言(而不是在发布给客户的版本中)。

    【讨论】:

    • 如果不好的先决条件等来自代码完全在你的控制之下,那么断言失败是可以的。但是像这样的情况呢:缺少/错误的 dll,错误的注册表项等。
    【解决方案3】:

    我使用断言来检查任何不需要的程序状态:

    • 函数前置条件
    • 有时我会在每次 API 调用后将它们插入到宏中:glDrawArray(); checkOpenGLError();--checkOpenGLError() 将调用 getGLError()(如果打开)
    • 数据结构完整性:assert(something == null);
    • 有时 GDB 对我说谎(iOS SDK 3.2)。我用断言来证明这一点。

    请注意,“不需要的程序状态”不包括运行时自然发生的错误,例如由于权限或 HD 故障而无法打开用户选择的文件。在这些情况下,使用断言是不明智的。

    【讨论】:

      【解决方案4】:

      现在很多代码都有很多外部依赖和连接。这些天我不倾向于使用传统的断言,我喜欢例外。我觉得我不能假设“这永远不会发生”,并且可以在非调试版本中安全地删除检查。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-06-30
        • 2023-04-02
        • 2011-04-15
        • 2017-04-10
        • 2012-03-19
        • 2018-05-12
        • 2018-12-11
        • 1970-01-01
        相关资源
        最近更新 更多