- Published on
UE 中的 断言宏 Assertion Macros
- Authors
- Name
- Zihan Li
在C和C++编程中,assert
可在开发期间帮助检测和诊断不正常或无效的运行时条件。这些条件通常检查是否指针为非空、除数为非零、函数并非递归运行,或代码要求的其他重要假设。但每次检查会使得效率十分低下。某些情况下,assert
会在延迟崩溃发生之前发现导致该崩溃的bug,例如删除未来tick所需的对象,协助开发人员发现引起崩溃的根本原因。assert
的关键特性之一是不存在于发布代码中,这意味着不但不会影响发布产品的性能,也没有任何副作用。对 assert
最简单的理解就是:"断言"必须一律为true,否则程序会停止运行。
1. check() 宏
- 用途
check()
用于验证某个条件是否为真。如果条件为假,程序会立即中断运行,并输出错误信息(包括文件名和行号),以便开发者快速发现问题。这通常用于那些“绝不应该发生”的错误情况。 - 示例
check(MyValue == 1); // 如果 MyValue 不等于1,则程序会在这里中断
- 特点
- 在开发和调试阶段非常有用,因为它可以使程序在出错时立即停止,防止错误传播。
- 在最终发布的版本中,通常会将这些断言宏移除或禁用,以免对性能产生影响。
2. checkf() 宏
- 用途
checkf()
与check()
类似,但允许开发者提供格式化的错误信息。这在复杂条件下有助于输出更详细的上下文信息。 - 示例
checkf(MyPointer != nullptr, TEXT("MyPointer should not be null!"));
- 特点
- 格式化字符串可以帮助定位问题的具体原因和位置。
3. ensure() 宏
- 用途
ensure()
用于检测条件是否为真,但与check()
不同的是,当条件不满足时,它不会立即中断程序的执行,而是记录一条警告信息。这使得程序可以在检测到问题时继续运行,适用于那些虽然不理想但不致命的情况。 - 示例
if (ensure(MyActorPointer)) { // 即使 MyActorPointer 为 null,程序依然会继续执行,但会在日志中记录警告信息 MyActorPointer->DoSomething(); }
- 特点
- 适合用于可能出现错误但不会导致程序崩溃的场景。
- 可以帮助开发者在运行时观察潜在问题,而不必中断整个应用程序【citeturn0search0】。
4. ensureAlways() 宏
- 用途
与ensure()
类似,但在同一条件多次不满足的情况下,每次都会记录警告,而不会像ensure()
那样只触发一次。这在需要持续监控某个条件的场景下非常有用。
5. 为什么使用断言宏?
- 调试定位问题
断言宏能在程序运行时立即捕捉到逻辑错误和不符合预期的状态,帮助开发者尽早发现问题并调试。 - 开发安全性
在开发过程中,如果某个关键条件不满足,断言会阻止程序继续运行,防止错误扩散并导致更复杂的问题。 - 性能影响
这些断言在开发版中非常有用,但在最终产品中通常会被禁用或移除,从而确保不会对性能产生影响。
总结
在UE中,常见的断言宏如 check()
、checkf()
、ensure()
和 ensureAlways()
,各有侧重:
- check()/checkf():用于那些“绝不允许出错”的情况,一旦条件不满足,立即中断程序。
- ensure() / ensureAlways():用于检测非致命错误,记录警告后允许程序继续运行,便于在不中断程序的情况下进行问题追踪。