使用vscode 进行调试Node + C++

如何使用vscode 调试 nodejs + C++

先讲遇到的问题

Electron 部分发新版本,windows包,在一些设备上出现了崩溃,没有堆栈,没有可用信息,怀疑的点有一大堆。

以上是问题,解决思路是从git提交记录进行比对找出一些最怀疑的点进行日志跟踪,尝试找出崩溃发生前最后日志出现位置,推测上下文。

如何定位问题先不细讲,最后大致定位在native log日志部分,比如表现,在一些机器上关掉调用就可以正常,打开调用就会崩溃。

确定了崩溃发生的位置,因为在不同的机器上才会有不同的表现,所以崩溃发生的原因还是不太详细,而且初始化调用的顺序是js端先调用node文件c++暴露的接口,传递需要初始化的完整路径,node 文件将加工后的路径交给log日志系统进行业务的初始化。因为出现问题,所以整个环节都是可以怀疑的地方。

如何缩小怀疑范围

比如从语言层面来讲,C++ 内部的相互调用机制这个基本可以排除怀疑,所以基本大概率怀疑的点应该是语言之间的交互部分,nodejs 提供的C++ Addon 部分就是怀疑对象的重点。

从结构来分,设计方案来讲,C++核心业务方是独立的模块儿,内部的逻辑和调用规则非常清晰,大概率问题不大。从语言交互部分来讲,如果按照规则使用问题也应该很少,对于整块儿业务来讲,这里出问题了,需要去排查,逐个排除。

发现规律应该能够减少更多的怀疑部分,比如这次遇到问题的时候发现在开发的机器上面没有任何问题,在用户的机器上面就能必现。不同的点就是用户的home 文件夹是使用中文的,开发和测试侧使用的是英文,开发侧有足够的依赖库可以正常使用,用户侧不确定是否全部包含。

目标锁定为中文是因为日志系统测试阶段没有考虑过中文路径,在开发时候会发现日志系统在windows 有额外处理部分,比如正反斜杠。

验证猜测

C++ 核心功能部分被编译为了静态库,先编译debug 静态库,然后新建console 工程 载入和使用,打断点就能确认是否好使。确认传入的中文路径在日志初始化状态没有任何问题。这块儿基本排除了因为C++ 的可能性。所以下一步测试从JavaScript 层传入中文路径,看Node 文件在接收参数之后传递给C++ 的值到底会是什么。带来一个新的问题,如何调试,如何断点。单一的打log并不能很直接的跟踪定位到问题所在,个人经验,跟踪log来解决手头问题令人抓狂又很低效。

调试需要用的工具

我们拿到关键字去搜索发现,可以debug C++ ,vscode 有插件儿 CodeLLDB ,因为需要调试C++ ,所以 C++ 调试插件 不可少,需要调试node ,nodejs 系统安装也需要必备。

  • Debugging on Linux (x64 or ARM), macOS and Windows*,

  • Conditional breakpoints, function breakpoints, data breakpoints, logpoints,

  • Launch debuggee in integrated or external terminal,

上面是CodeLLDB 的介绍,可以在不同的平台方面提供断点等debug 功能。

**C/C++ **插件儿不多解释,需要断点C或者C++ 不是。

至于 Nodejs ,今天需要讲的重点,断点需要调试的就是 Nodejs addon,从JavaScript 启动可以断点js ,也可以断点到执行到的C++ 部分。

怎么做

先讲怎么做,然后再说为什么。

讲一下为什么

需求是需要跨平台 debug nodejs 和c++ 部分,编辑器是vscode。从vscode 的插件儿开始入手。C++ 和 Nodejs 属于必备,关心的重点就是CodeLLDB。

如何使用CodeLLDB,比如他们快速开始。

"CodeLLDB_quick_start"

name Launch configuration name. 明显是指的标识,type 应该是告诉vscode 需要执行哪一类调试。

request: The request property of the configuration chooses how it will be done。 可以暂时理解为目的。

program:Path to the debuggee executable. 需要launch执行的路径。

args: Command line parameters. If this is a string, it will be split using shell-like syntax. 执行时候需要传递的参数

cwd: Current Working directory. 当前工作路径

1
2
3
4
5
6
7
8
{
"type": "lldb",
"request": "launch",
"name": "lldb:node",
"program": "node",
"args": ["--inspect-brk", "--expose-gc","main.js"], // --inspect-brk 参看nodejs , node --expose-gc main.js 可以手动代码执行gc()
"cwd": "${workspaceFolder}",
}

上面的这边在使用的lldb launch 配置。

"nodeinspect"

在使用launch的时候我们使用了inspect 的参数,于是当我们真正调试的时候,需要监听的端口号为9229。

1
2
3
4
5
6
7
8
9
{
"type": "node",
"request": "attach",
"name": "node:attach",
"port": 9229,
"skipFiles": [
"<node_internals>/**"
]
}

有了上面的基本介绍,这里的一些参数似乎显得就是很自然的一些内容。skipFiles vscode nodejs debug介绍

因为需要经历两个步骤,先launch 需要debug 的内容,然后attach 住正在执行的内容,才能够达到debug 的目的。

compounds: vscode 提供了这个字段,很明显是为了大家执行方便,让逻辑按照执行顺序去执行。

preLaunchTask字段,从字面意思就能了解是在做一些列操作之前可以先执行某种动作。

compounds

演示的视频是在Mac 下面做的,在windows下面配置部分会略微不同,但是流程是一样的,需要先launch ,然后在attach node 文件,进而在需要的地方进行断点。

附加: :视频中用于测试的Demo 工程 Git 地址 git@github.com:waitingchange/vscode_debug_nodejs_cpp.git