今天回答问题的时候,正在WSL下测试,想着就不启动巨无霸VS了,直接WSL下完成问题复现、bug定位、修改。
配置环境
目标:VS Code 里写代码,代码运行、调试跑在 WSL 的 Linux 系统中。
配置好后,操作基本都在 VS Code 中完成,对不熟悉 Linux 的新手来说,也是很简单容易的。
先看看正在用的是哪个发行版 wsl --list --verbose
NAME STATE VERSION
* Ubuntu-22.04 Stopped 2
由于 Windows 有了 Linux 子系统,对我们来说简单的安装使用即可,想深入研究 WSL 的请看这里 Windows WSL文档1。
如果没有安装,看下面👇
安装 WSL
发现这位博主讲的很详细了,需要的直接移步 史上最全的WSL安装教程2。
VS Code 连接 Linux
准确的说,是让 VS Code 连接到 WSL 中的 Linux 系统,并不复杂,装个扩展就可以了:打开 VS Code ,点击左侧导航栏的扩展,安装扩展,我的环境里安装的是 WSL,但似乎网络上其他人用的都是 Remote Development,简单看了下,似乎差不多。
或
安装后,点击左下角任务栏或者 CTRL + SHIFT + P 打开命令面板,输入 WSL
选择 WSL:Connect to WSL :
如果一切正常,状态栏最左侧将显示连接到的 Linux 版本信息,如上。
写代码
这一步其实不需要多说,但对第一次接触 WSL 或 Linux 的新手来说,有一些需要注意的小细节,简单说明下。
CTRL+ALT+WINDOS+N 新建文件,输入文件名,此时会让你选择存储路径,注意,这个路径是连接到的 WSL 中的 子系统中的路径,而不是实体机系统的路径。当然,也可以选择本地真实系统的路径,点击【Show Local】即可。
文件保存成功后,就可以愉快的写代码了。
控制台
在 VS Code 中,所有对 WSL 的操作都可以在不离开 VS Code 的环境下完成,即 控制台。
CTRL+J 打开面板的【TERMINAL】页面,这里面展示的就是我们所连接到的 Linux 系统的控制台界面。
例如,我们上面写完保存了代码,想看看文件是否真的保存了,可以在这里,cd换到代码保存路径,ls -l,如果能看到 我们刚刚写的 foo.c,说明一切正常,也可以 cat/vim 看看里面的内容。
后续的编译、调试 都是在控制台中完成的,不再赘述。
编译
编译命令
g++ -g foo.c -o foo,
因为我们需要调试,所以需要附加 -g 参数:
-g 编译带有调试信息的可执行文件, 调试信息是调试器gdb使用的调试信息,用来调试程序, 调试信息和可执行文件在统一输出文件中,带有调试信息的可执行文件大小会大很多。
-o 则表示生成的目标文件名,顺利编译通过则会发现目录下多了个 foo 文件。
./foo 运行起来,如果代码中有异常,可能就会见到如下提示
Segmentation fault
OK,是时候调试了。
调试
Segmentation fault 即段错误,一般来说就是访问了野指针、递归调用太深、数组太大等。但本身系统是可以为崩溃的程序产生dump进而调试的,从上面的输出来看,并没有生成core dump,为何?
我们确认下:
ulimit -a
如果返回的信息为
core file size (blocks, -c) 0
说明core dump的设置大小为0,无法产生dump,设置一下:
ulimit -c unlimited
再次运行程序,输出
Segmentation fault (core dumped)
但,dump 生成到了哪里呢?
cat /proc/sys/kernel/core_pattern
默认是在 /mnt/wslg/dumps 下以 core.+程序名命名,如 core.foo
core dump 生的规则还受如下因素影响:
- /proc/sys/kernel/core_uses_pid 可以控制core文件的文件名中是否添加pid作为扩展。
文件内容为1,表示添加pid作为扩展名,生成的 core文件格式为core.xxxx;为0则表示生成的core文件同一命名为core。
可以用命令查看当前值:
cat /proc/sys/kernel/core_uses_pid
或者修改值:
echo"1" > /proc/sys/kernel/core_uses_pid
- proc/sys/kernel/core_pattern 可以控制core文件保存位置和文件名格式。
可以用命令查看当前值:
cat proc/sys/kernel/core_pattern
或者修改值:
echo"/corefile/core-%e-%p-%t" >proc/sys/kernel/core_pattern
可以将core文件统一生成到/corefile目录下,产生的文件名为core-命令名-pid-时间戳
启动 gdb 调试
gdb foo /mnt/wslg/dumps/core.foo
输入 bt (backtrace)命令,查看详细的调用堆栈,此时已经可以对应到源码
甚至,鼠标悬浮在 foo.c 上,按住CTRL+左键单击,可以跳转到代码对应的行,是不是太方便了?
gdb 十分强大3,常用的调试命令还有n(next)、 s(step)、f(frame)、i(info) 等。
如果想学习 gdb 调试,或者跑起简单的代码,甚至可以直接用在线工具4。
上面的程序之所以能够被调试,是因为编译时附加了调试信息(g++ -g),否则是无法显示关联到源码的调用堆栈信息的。那么,怎样判断一个程序是否附带了调试信息呢,可以通过如下命令查看
readelf -S foo|grep debug
[28] .debug_aranges PROGBITS 0000000000000000 00003036
[29] .debug_info PROGBITS 0000000000000000 000030c6
[30] .debug_abbrev PROGBITS 0000000000000000 00005867
[31] .debug_line PROGBITS 0000000000000000 00005ea4
[32] .debug_str PROGBITS 0000000000000000 000060d2
[33] .debug_line_str PROGBITS 0000000000000000 00007469
[34] .debug_rnglists PROGBITS 0000000000000000 000076e4
总结
对于 Windows 上的程序员来说,这是个体验 linux 开发的简便方式。
相比简便的WINDOWS IDE式开发,Linux 开发是另外一个繁荣庞杂的世界,值得每个致力于开发的程序员去探索,相信会带给你不一样的体验。