调试提示

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

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

  1. 在命令行 shell上使用“.eqp full”选项

    当您有一个正在调试或试图理解的 SQL 脚本时,使用“.eqp full”设置在命令行 shell中运行它通常很有用。当“.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 正在使用的变量。以下例程可用:

    • void sqlite3ShowExpr(const Expr*);
    • void sqlite3ShowExprList(const ExprList*);
    • void sqlite3ShowIdList(const IdList*);
    • void sqlite3ShowSrcList(const SrcList*);
    • void sqlite3ShowSelect(const Select*);
    • void sqlite3ShowWith(const With*);
    • void sqlite3ShowUpsert(const Upsert*);
    • void sqlite3ShowTrigger(const Trigger*);
    • void sqlite3ShowTriggerList(const Trigger*);
    • void sqlite3ShowTriggerStep(const TriggerStep*);
    • void sqlite3ShowTriggerStepList(const TriggerStep*);
    • void sqlite3ShowWindow(const Window*);
    • void sqlite3ShowWinFunc(const Window*);

    这些例程不是 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 接口禁用。如果使用“--lookaside 0 0”命令行选项启动, 命令行 shell将使用该接口禁用后备。