跑测试时终端刷出一行 AssertionError,或者打开某个软件弹出「Assertion failed」,点确定程序就退了。这不是系统崩溃,是代码自己发现不对劲,主动停下来的。

断言是干什么的

assert 是编程语言里的检查语句,后面跟一个条件,条件为真就继续,为假就报错终止。C 语言里写 assert(p != NULL),指针为空时直接 abort,并打印文件名和行号。Python 的 assert 失败抛出 AssertionError,Node.js 的 assert 模块会抛出带差异信息的 AssertionError。它的用途是抓「本不该发生」的情况,不是处理用户输入错误。Java 的 assert 默认关闭,运行时加 -ea 参数才生效。

报错信息怎么读

C 里的典型输出会带上断言表达式、文件名和行号。先看表达式,再看文件和行号,去源码对应位置找上下文。Python 会给出 Traceback,最下面一行就是出错的位置,往上翻能看到一层层调用链和传进来的参数。浏览器控制台或测试框架会给期望值和实际值,两个数一对,问题基本就露出来了。

常见触发原因

  • 指针或对象为空,代码假设它一定有值。
  • 数组下标越界,或者容器长度和实际不符。
  • 函数参数不满足前置条件,比如要求正数传了 0。
  • 多线程下数据被改,条件检查的瞬间就失效了。

怎么处理才算对

别急着把 assert 删掉或者注释掉,那等于把烟雾报警器拆了。先复现,记录输入和调用栈,用调试器断在断言处看变量值。确认是代码逻辑问题就修逻辑,确认是外部数据问题就在入口做校验。发布版本一般会定义 NDEBUG 关掉 assert,所以它不能代替错误处理,用户输入该判断还得判断。断言和异常不是一回事,断言查的是程序内部逻辑,异常处理的是可预期的运行时错误。日志里记下断言所在的函数和参数,方便复现,顺手补一个回归测试,防止下次再犯。

看到这类报错,正确的反应是「哪个假设不成立」,找到那个前提,比改报错文字有用。