Linux搭建C开发环境
本篇文章基于WSL2 Ubuntu,使用CMake搭建 VSCode + C 的编译调试开发环境,本质上适用于所有Linux系统。
也可以从github上克隆示例项目[1]到本地,直接启动调试。
1.安装编译调试环境
1 |
|
2.初始化工程结构
2.1 终端创建目录以及文件
1 |
|
c_cpp_properties.json也可以通过VSCode自动生成: 在VSCode中Ctrl + Shift + P
调出控制命令台,输入并选择C/C++ Edit Configurations(JSON)
,VSCode会自动生成合法的配置。
2.2 打开VSCode工作区
1 |
|
2.3 复制内容到对应文件
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
2.4 工程目录结构参考
以上准备工作结束后,工程的目录结构如下图所示,其中
include
文件夹放置头文件,例如:sha256.h
source
文件夹放置源文件,例如:sha256.c
3.编译调试
F7
编译,F5
启动调试(F5
包含编译的过程),按照launch.json
的StopAtEntry:true
的定义,程序应该暂停在main
4.调试入门
所有语言以及IDE在调试的逻辑上基本是一致的,甚至连调试的快捷键也可能相同。比如MDK和VSCode的调试快捷键完全相同,虽然两者完全不具备可比性。VSCode官方介绍的Debugging用法[2]。
4.1 断点
断点作为调试中最重要的功能,常用的有三种,普通断点、条件断点和日志断点
4.1.1 普通断点
在一行语句上创建断点,启动调试后,程序会在该语句前暂停,即断点所在的行未被执行。以下图为例,程序执行到该断点处,b的值为0,说明语句b = debug_func(a);
未被执行。继续往下执行,则b的值变为45,说明语句执行了。
4.1.2 条件断点
Conditional Breakpoint
,条件断点,当程序符合预设的条件时,暂停在断点处,其标志是断点符号中有个等号。条件断点一般有两种情况,符合表达式或者命中次数。命中次数可以简单理解为该语句执行了多少遍。以下图为例,创建一个条件断点,Expression
表达式i > 5
与Hit Count
命中次数5
是等价的。
GDB调试器不一定支持Hit Count
断点,启动调试后提示Breakpoints of this type are not supported by the debugger
,该断点退化成普通断点。
增加一个变量,统计函数的运行次数,使用Expression
的条件断点能够达到与Hit Count
一样的效果。
4.1.3 记录点
当程序不方便暂停调试时,可以添加记录点
,或者叫Logpoint
。其符号是方块形状,在DEBUG CONSOLE
控制台输出日志。如果称其为日志断点则不是很合适,因为程序没有暂停运行,不符合断点的概念
4.1.4 内联断点
内联断点,即Inline Breakpoint
,用于调试一行代码中包含多个语句的情况。以下图为例,在for
循环语句中,虽然只有一行代码,但是该行包含了3个语句:int i = 0
和i < a
以及i++
。因此内联断点需要在指定的列前添加并显示。
在实际的工程项目中,如果工程遵守合理的编码规范的情况下,内联断点是基本用不上的。
4.1.5 函数断点
创建函数断点:选择Run
->New Breakpoint
->Function Breakpoint
,输入函数的名称,断点创建成功。该方式可以但没必要,不如直接在函数的入口打一个普通断点来的方便。
4.2 监控变量
4.2.1 基础变量
Watch
窗口可以查看所有类型的变量
- 数值类变量
int
,float
,double
- 字符类型,先显示十进制的数值再显示
ASCII
对应的字符 - 字符串(本质上是字符串指针),先显示地址再显示字符串的值
- 自定义的结构体以及枚举,枚举会显示枚举名称
4.2.2 不同进制
以int变量a
为例,a
默认以十进制的值显示,a,h
以十六进制显示, a,b
二进制,a,o
八进制
4.2.3 表达式
监控变量窗口可以直接计算出表达式的结果
4.2.4 指针
如果监控一个void
类型的指针,监控窗口只会显示指针地址,使用强制类型转换才能正确显示字符串或结构体或数组的具体值。下图展示void
类型的指针转换为字符串指针或者结构体指针用法
强转数组则有一点区别,因为只强转数组的类型是不够的,还需要指定长度。假设需要强制指针array_ptr
成长度为10的int数组,则表达式如下
1 |
|
4.3 调用堆栈
以一个递归为例子,从1累加到5,预期进入5次递归函数。左侧的CALL STACK
就会显示当前程序的调用栈。切换栈的深度时,观察arg
的值
4.4 快捷键
熟练常用的调试快捷键非常重要,在实际项目中的效率远高于按钮点击的方式。
快捷键 | 英文 | 中文 | 描述 |
---|---|---|---|
F5 |
Continue | 继续 | 继续运行到下一个断点 |
F10 |
Step Over | 单步跳过 | 执行一行代码 |
F11 |
Step In | 单步执行 | 进入函数 |
Shift + F11 |
Step Out | 单步停止 | 跳出函数 |
F9 |
Toggle Breakpoint | 切换断点 | 添加或者删除断点 |
F5
F10
F11
Shift + F11
5.导入C文件
根据当前的CMake规则,所有在include
和source
文件夹下的C文件会自动加入编译链接。以导入sha256
库[4]为例子,计算一个从1到10的数组的哈希值
1 |
|
使用在线哈希计算工具验证计算结果[5]。
6.终端编译运行
1 |
|