在 CLion 中进行调试
使用 IDE 而不是纯文本编辑器的关键优势之一在于调试体验。 调试涉及能够在任意点暂停程序执行并且能够检查变量的内容。
CLion 支持使用 GDB 调试器(从 1.1 版起在 OS X 上,从 2016.2 版起在 Linux 上使用 LLDB)的调试体验。 这里是一些支持的核心调试功能。
Upd. (自 CLion 2016.1 和 2016.2 以来的变化)
了解如何将调试附加到本地进程,不是从 CLion(从 CLion v2016.1)开始。
查看 GDB 和 LLDB 驱动程序的主要变化(自 v2016.2 以来),并且解决了如下问题:
- 命令超时。
- 单步执行问题。
- 调试器性能问题。
请点击链接,在我们的博客寻找更多详情。 试试远程 GDB 调试(自 v2016.2)。
断点
为了检查程序在特定点的状态,您需要暂停程序。 断点正是用于此目的。简单的断点会在特定行停止执行程序。 只需按下 Ctrl+F8 (Windows/Linux)/⌘F8 (OS X),或者也可以在代码左侧的灰色沟槽区域点击鼠标,这样即可设置断点。 将高亮显示带有断点的行,而断点则显示为红圈。
现在,当您在调试模式(选择菜单 运行|调试 (Run|Debug) 或按下 Shift+F9 (Windows/Linux)/^D (OS X))下运行程序,程序将停在您选定的行。
如果某些条件成立,有条件断点将只停在特定行。 编辑条件的方法是:右键点击断点,然后在弹出窗口中输入条件。 编辑器中甚至提供代码补全!
当这个弹出窗口打开时,您可以按下 Ctrl+Shift+F8 /⇧⌘F8 ,即可打开完整的断点编辑窗口:
这里提供的一些选项包括:
- 暂停 (Suspend) — 此复选框确定执行是否在特定点暂停执行。 未选中意味着将继续执行程序,但仍将执行任何断点规则(例如,记录日志)。
- 条件 (Condition) — 确定触发断点的条件。 留空意味着总是命中断点。
- 将消息记录到控制台 (Log message to console) 向控制台写入有关命中断点的信息。
- 记录已评估的表达式 (Log evaluated expression) 让您记录特定评估的结果。
- 命中后删除 (Remove once hit) 确保命中断点后删除该断点。 如果您只想记录第一次命中特定点,那么这可能很有用。
- 禁用直到命中选定断点 (Disabled until selected breakpoint is hit) 正如其所述一样:它禁用当前断点,直到遇到某个其他断点。 这在这种情况下很有用,例如,您只想调查代码中的某点,而该点从选择的特定函数调用。 有两种选择:
- 再次禁用 (Disable again) 断点命中后禁用该断点,直到再次命中依赖的断点(在这种情况下,它被重新启用)。
- 保持启用 (Leave enabled) 保持一直启用断点,因此不再依赖于任何其他首先命中的断点。
异常断点
但那不是全部! 除了一般的断点外,CLion 还支持异常断点,这种断点正如其名,在程序抛出异常时触发。
与异常断点相关的选项集类似于行断点:您可以指定是否暂停执行,将消息记录到控制台,命中它后删除异常,或者只在首先命中某个其他断点时才启用它:
调试器用户界面
那么,当调试器命中断点时,究竟会发生什么呢? 除了暂停执行外,您还会看到以下调试工具窗口:
这里有很多内容,所以我们首先讨论两个主要标签(顶级标签,可以这么说)。 它们是:
- 调试器 (Debugger) — 这实际上显示了我们将在稍后讨论的各种调试选项。
- 控制台 (Console) — 如果您的应用程序有任何输出,那么该区域显示命令行输出。
在这些选项卡的右边有一系列按钮,这些按钮使您可以在调试的代码中导航。 其中包括让您:
- 显示执行点 (Show Execution Point) (Alt+F10 ),
- 逐函数执行 (Step Over) (F8 ),
- 逐行执行 (Step Into) (F7 ),
- 强制逐行执行 (Force Step Into) (Alt+Shift+F7 ),
- 跳出 (Step Out) (Shift+F8 ),
- 和运行到光标 (Run to Cursor) (Alt+F9 )。
还有一个按钮使您可以评估任意表达式 (Evaluate Arbitrary Expression) (Alt+F8 ) — 我们将稍后再谈这项功能。
选项卡左侧是一列垂直按钮,其中包含更高级的调试控制,包括恢复执行或停止应用程序的按钮,显示断点设置的功能以及其他各种控制。
我们回到 Debugger 选项卡。 这个选项卡中有大量内容。 首先,在左边,它让您可以实际上选择要检查的线程。 现代应用程序在许多线程上运行,因此您可以从下拉列表中选择一个:
在其正下方是堆栈框架,即在您执行代码时调用的嵌套函数列表。 每条记录都列出了函数(或构造函数)全名、文件名和行号。 单击该行会使 CLion 在指定的行号处打开相应的文件:
在堆栈框架右侧有两个选项卡:变量 (Variables) 和 GDB (LLDB)。 我们将稍后谈论变量;就 GDB (LLDB) 而言,该选项卡基本上显示了 GDB (LLDB) 自身的命令行输出,因为那是用于调试我们应用的调试器。
变量
最简单的查看变量状态的方法当然是在代码中。 只需将鼠标悬停在存疑的变量上,就会看到如下内容:
如果此时按下 Ctrl+F1 (Windows/Linux)/⌘F1 (OS X),将弹出一个窗口,其中包含您想查看的变量的内部状态:
当然,您可以在 Debug 工具窗口更全面地了解变量。 对于堆栈框架中的选定函数,Variables 选项卡显示所有变量的状态。 在复杂的应用程序中,它可能会非常繁忙:
对于任何一个变量,我们可以展开树以查看其内容:
如果您想稍微减少内容,只需右键点击变量,然后选择检查 (Inspect):将打开一个单独的窗口,仅检查此变量:
完全可以在调试会话中实际更改变量值。 右键点击变量并选择设置值 (Set Value)。 编辑器将为当前值就地打开输入栏,让您输入新值:
GNU STL 渲染器
作为调试体验的特殊增强,CLion 特别小心对待 STL 容器,确保在调试过程中让您获得最佳表示。 例如,这里是在调试器中如何显示 std::map :
这项功能适用于 GCC,而对于 Clang,它只适用于 libstdc++。 需要在 CMakeLists.txt 中添加以下设置:
set(CMAKE_CXX_FLAGS “${CMAKE_CXX_FLAGS} -stdlib=libstdc++”)
监视
在每个点捕获每个变量会导致信息过多。 有时,您希望关注特定变量及其在程序的整个执行过程中的变化方式,包括当考虑的变量不是您正检查代码的本地变量时,监视变化情况。 这正是 Debug 工具窗口的监视 (Watch) 区域的作用。
只需按下 增加 (Add) 按钮 (Alt+Insert (Windows/Linux)/⌘N (OS X)),然后输入待监视的变量名称,即可开始监视变量。 此处也提供代码补全。
也可以选择现有变量,右键点击它,然后选择添加到监视 (Add to watches)。 现在,即使您处于堆栈框架的某些嵌套部分,窗口也将继续显示变量的值:
评估表达
您可以在断点上看到变量状态,但是如果要查看两个变量的总和,或者当场评估函数调用的结果怎么办? 也有用于这种目的的功能。 只需按下 Debug 工具窗口上的评估表达式 (Evaluate Expression) 按钮 (Alt+F8 ),然后输入表达式即可。 和往常一样,这里也有代码补全,按下评估 (Evaluate) 按钮后,下面的结果区域将显示评估结果:
也可以使用快捷键 (Ctrl+Shift+Enter ),将该表达式添加到监视中。 是的 – 监视可以包含任意表达式,而不仅仅是单个变量!
观察 CLion 调试功能:
https://www.youtube.com/watch?v=wUZyoAnPdCY
结论
本文阐述了调试时 CLion 能做什么。 您可以在 30 天内免费评估这些功能,只需从我们的网站下载最新CLion。 试用一下,然后告诉我们您的看法!
原文发表于2015年8月,作者Dmitri Nesteruk