小巧。快速。可靠。
三选二。

调试提示

以下是 SQLite 开发人员用来跟踪、检查和理解 SQLite 核心库行为的一些随机技巧。

这些技巧旨在帮助理解 SQLite 核心库本身,而不是仅仅使用 SQLite 的应用程序。

  1. 命令行 shell 中使用 ".eqp full" 选项

    当您有一个正在调试或试图理解的 SQL 脚本时,通常很有用的是在 命令行 shell 中使用 ".eqp full" 设置运行它。当 ".eqp" 设置为 FULL 时,shell 会在实际运行每个命令之前自动显示该命令的 EXPLAINEXPLAIN QUERY PLAN 输出。

    为了提高可读性,还可以设置 ".echo on",以便输出包含原始 SQL 文本。

    较新的 ".eqp trace" 命令执行 ".eqp full" 执行的所有操作,并且还开启 VDBE 追踪

  2. 使用编译时选项启用调试功能。

    建议的编译时选项包括

  3. SQLITE_ENABLE_TREETRACE 和 SQLITE_ENABLE_WHERETRACE 选项在 编译时选项 文档中没有记录,因为它们不受官方支持。它们的作用是在命令行 shell 中激活 ".treetrace" 和 ".wheretrace" 点命令,分别为生成 SELECT 和 DML 语句以及 WHERE 子句代码的逻辑提供低级跟踪输出。

  4. 从调试器调用 sqlite3ShowExpr() 及类似函数。

    当使用 SQLITE_DEBUG 编译时,SQLite 包含一些例程,这些例程会将各种内部抽象语法树结构打印为 ASCII 艺术图。这在调试中非常有用,以便理解 SQLite 正在处理的变量。以下例程可用

    这些例程不是 API,可能会发生变化。它们仅用于交互式调试。

  5. 在 test_addoptrace 上设置断点

    调试 字节码 生成器时,通常需要知道某个特定操作码是在哪里生成的。要轻松找到它,请在调试器中运行脚本。在 "test_addoptrace" 例程上设置断点。然后运行 "PRAGMA vdbe_addoptrace=ON;",然后运行有问题的 SQL 语句。每个操作码在附加到 VDBE 程序时都会显示,并且断点随后会立即触发。单步执行直到到达操作码,然后在堆栈中向后查看以了解它是如何以及在哪里生成的。

    这仅在使用 SQLITE_DEBUG 编译时有效。

  6. 使用 ".treetrace" 和 ".wheretrace" shell 命令

    当命令行 shell 和 SQLite 核心库都使用 SQLITE_DEBUG 和 SQLITE_ENABLE_TREETRACE 以及 SQLITE_ENABLE_WHERETRACE 进行编译时,shell 就会有两个命令用于打开代码生成器最复杂部分的调试功能 - 分别处理 SELECT 语句和 WHERE 子句的逻辑。".treetrace" 和 ".wheretrace" 命令都接受一个可以用十六进制表示的数字参数。每一位都打开调试的不同部分。通常使用 "0xfff" 和 "0xff" 的值。使用 "0" 作为参数可关闭所有跟踪输出。

  7. 使用 ".breakpoint" shell 命令

    CLI 中的 ".breakpoint" 命令什么也不做,只是调用名为 "test_breakpoint()" 的过程,该过程是一个空操作。

    如果您有一个脚本,并且想要从该脚本中间的某个点开始调试,只需在 gdb(或您使用的任何调试器)中在 test_breakpoint() 函数上设置断点,并在您想要停止的地方添加 ".breakpoint" 命令。当您到达第一个断点时,设置您需要的任何其他断点或变量跟踪。

  8. 禁用 备用内存分配器

    在查找内存分配问题(内存泄漏、释放后使用错误、缓冲区溢出等)时,有时禁用 备用内存分配器 然后在 valgrind 或 MSAN 或其他一些堆内存调试工具下运行测试会很有用。可以使用 SQLITE_CONFIG_LOOKASIDE 接口在启动时禁用备用内存分配器。如果 命令行 shell 使用 "--lookaside 0 0" 命令行选项启动,它将使用该接口禁用备用内存分配器。