Menu
CoddyTech

运行时错误是什么?

运行时错误(runtime error)是程序运行过程中发生的错误:某个操作无法用当前的值完成,比如除以零,或者读取超出列表末尾的位置。除非错误被处理,否则程序会在这一行停下来。

作者 Kevin Spektor, 联合创始人兼 CTO

更新于 2026年9月24日

运行时错误会一直等到程序已经运行起来才出现。代码在启动前通过了所有检查,正常运行了一段时间,然后遇到一个无法用当时的值完成的操作。下面这个函数对一个列表没问题,对另一个列表却会失败:

85.0
Traceback (most recent call last):
  File "main.py", line 5, in <module>
    print(average([]))
          ^^^^^^^^^^^
  File "main.py", line 2, in average
    return sum(scores) / len(scores)
           ~~~~~~~~~~~~^~~~~~~~~~~~~
ZeroDivisionError: division by zero

第一次调用打印 85.0。第二次调用传入了一个空列表,所以 len(scores) 是 0,除法无法进行。语法没有任何问题,所以这不是语法错误。问题只在某些数据下才存在,这就是为什么一个程序正常运行了一百次之后,仍然可能出现运行时错误。

运行时错误发生时会怎样

  1. 程序执行到一个操作,这里是 sum(scores) / len(scores)。
  2. 运行环境在执行之前先检查这个操作。CPython 在做除法前会检查除数,JVM 会检查每一个数组索引,Python 在返回字典的值之前会检查键是否存在。
  3. 检查没有通过,运行环境就创建一个错误对象。在 Python 和 Java 中,这个对象就是异常,它记录了错误类型、一条信息以及出错的位置。
  4. 运行环境寻找处理这类错误的代码,先在当前函数里找,再到调用它的函数里找,依次向外层查找。
  5. 如果没有任何代码处理它,程序就会停止。Python 打印一段 traceback,并以状态码 1 退出。Java 打印一段以 Exception in thread "main" 开头的堆栈跟踪。

没有这些检查的语言表现就不一样了。C 语言不检查数组索引或指针,所以一次错误的内存访问要么悄悄地破坏数据,要么让操作系统以段错误终止程序。

程序在出错那一行之前做的所有事情都已经发生了。下面这个循环先打印了三种颜色,在第四次时才失败:

red
green
blue
Traceback (most recent call last):
  File "main.py", line 4, in <module>
    print(colors[i])
          ~~~~~~^^^
IndexError: list index out of range

如何阅读 traceback

Python 的 traceback 要从下往上读。最后一行写着错误类型和信息:ZeroDivisionError: division by zero。上面的几行列出了调用链,最早的在前,最近的在后。在第一个例子中,第 5 行调用了 average,而 average 内部的第 2 行就是除法失败的地方。

出错的那一行,并不总是需要修改的那一行。average 的第 2 行本身没有问题。真正的问题是空列表是怎么传到这里的,所以要顺着这个错误的值往回追,找到它的来源,在那里修复。如果 traceback 经过了不是你写的库文件,就找最后一行指向你自己文件的那一行。

常见的运行时错误

下面的每条信息都直接复制自 Python 3.12。

错误示例信息
ZeroDivisionError10 / 0division by zero
IndexError["red", "green", "blue"][3]list index out of range
KeyError{"theme": "dark"}["font"]'font'
ValueErrorint("twenty")invalid literal for int() with base 10: 'twenty'
TypeError"Total: " + 5can only concatenate str (not "int") to str
AttributeError对 None 调用 .upper()'NoneType' object has no attribute 'upper'
FileNotFoundErroropen("missing.txt")[Errno 2] No such file or directory: 'missing.txt'
RecursionError一个无限调用自身的函数maximum recursion depth exceeded

Java 有直接对应的异常,比如 ArithmeticException、ArrayIndexOutOfBoundsException、NumberFormatException 和 NullPointerException。在 Java 中,一次没有被捕获的整数除以零会打印:

Exception in thread "main" java.lang.ArithmeticException: / by zero

JavaScript 对数字更宽容:10 / 0 的结果是 Infinity,而不是错误。它会在你使用一个不存在的值时出错。当 user 是 undefined 时,Node.js 对 user.name 打印:

TypeError: Cannot read properties of undefined (reading 'name')

如何修复运行时错误

  1. 复现它。用同样的输入再运行一次程序,确认出现的是同一个错误。
  2. 阅读 traceback 的最后一行,然后在你自己的代码里找到对应的行。
  3. 查看相关的值。在出错的那一行之前把它们打印出来,或者用调试器在那里设一个断点停下来。
  4. 修复根本原因。改正索引,为特殊情况加上保护,或者在使用输入之前先验证它。

对于 average 函数,修复办法是先决定没有任何成绩时平均分应该是多少,再把这个决定写进代码:

85.0
0

有些失败是你无法控制的:文件被删除了,网络超时了,用户在该填数字的地方输入了字母。这些情况没法靠修改代码来避免,所以要用异常处理捕获它们,再决定程序接下来怎么做。你不应该做的,是用 try 把一个 bug 包起来藏住。循环多数了一步导致的 IndexError 是需要修复的错误,而不是需要捕获的异常。

Windows 和 Excel 中的运行时错误信息

这个术语也会出现在你自己的代码之外。如果 Windows 弹出一个标题为 Microsoft Visual C++ Runtime Library、内容带有 Runtime Error! 字样的对话框,说明某个用 C++ 编写的程序遇到了致命错误,被 C++ 运行库终止了。作为用户,你无法修改那段代码,所以通常的解决办法是更新这个程序,修复或重新安装 Microsoft Visual C++ Redistributable 运行库,如果是游戏,还可以更新显卡驱动。

用 VBA 编写的 Excel 宏会报告带编号的运行时错误。Run-time error '9': Subscript out of range 表示宏请求了一个不存在的工作表或数组元素,Run-time error '1004' 则是对工作簿、工作表或区域的操作失败时抛出的通用错误。道理和 Python 中一样:合法的代码遇到了它无法处理的值。

下一步学什么

运行时错误有两个“兄弟”:在程序启动前就被发现的语法错误,以及从不产生任何信息的逻辑错误。想让程序从运行时错误中恢复而不是直接崩溃,可以阅读异常处理,再看 Python 指南中的异常和调试错误。Python 课程的每一课都会让你编写和修复这样的代码。

常见问题

运行时错误和语法错误有什么区别?

语法错误在程序启动前就会被发现,因为代码违反了语言的语法规则,所以一行都不会运行。运行时错误发生得更晚,是在程序运行过程中,某一行合法的代码遇到了它无法处理的值。在它之前的每一行都已经运行过,可能已经打印了输出。

为什么我总是遇到运行时错误?

通常是因为代码对数据做了并不总是成立的假设:列表永远不会是空的,文件一定存在,用户一定会输入数字。每个假设对你测试过的输入都成立,却会在某个你没测试过的输入上失败。用空值、零、缺失值和非常大的输入来测试,并明确地检查或处理这些情况。

LeetCode 上的 Runtime Error 是什么意思?
意思是你的代码编译通过了,但至少在一个测试用例上崩溃了。常见原因有索引越界、除以零、使用了 null 或 None 值,或者递归太深导致栈溢出。把结果页面上显示的失败输入拿来自己运行一遍,并检查边界情况:空数组、只有一个元素,以及允许的最大规模。
运行时错误和异常是一回事吗?
不完全是。在 Python 和 Java 中,大多数运行时错误都以异常的形式报告,所以程序才能捕获它们。但 C 这样的语言有运行时错误,却根本没有异常。在 Java 中,RuntimeException 还是某一类异常的名字,也就是 NullPointerException 这类非受检异常。
编译器能发现运行时错误吗?

只能发现一部分。编译器或 mypy 这样的类型检查器可以证明某些错误不可能发生,比如把文本和数字相加。但它无法知道程序运行时才会传入的值,比如用户输入的一个数字恰好是零。这类错误只能通过运行代码来发现,或者通过检查输入来处理。

Coddy 编程语言插图

和 Coddy 一起学编程

开始