文章目录
1. Linux C/C++ 常见问题
1.1 多线程启动顺序依赖的问题
如一个线程依赖其他线程的启动,需控制启动顺序,比如B线程的循序前提是A线程运行,这样就需要使用条件变量进行阻塞等待,或者自定义变量进行等待处理。
1.2 多线程共享资源加锁问题
针对跨线程使用的非原子操作的资源,需要增加互斥锁等进行保护,如全局变量等。
1.3 内存泄漏问题
常用的问题有不正确的malloc/free或new/delete匹配、使用未初始化的指针、数组越界、踩内存等;可使用valgrind协助排查内存泄漏, 具体见5.3。
1.4 一些库32位64位不兼容问题
如32位ARM平台,交叉编译依赖库的时候,要编译为32位的库。
2.常用的问题定位方法
2.1 打印或者日志
一般的问题可通过打印或者日志进行问题的定位分析,日志可使用异步日志。
2.2 GDB
复杂一些的问题可使用GDB的方法进行定位问题,具体的两种方法见第二章节。
2.3 使用valgrind排查问题
对于一些踩内存的问题,GDB定位的地方不一定就是出错的地方,这个时候就需要使用valgrind来定位问题了;使用以下命令运行程序。
valgrind --log-file=./xxx.log --tool=memcheck --leak-check=yes --track-origins=yes ./xxx.bin
如果definitely lost和indirectly lost提示的部分不为0,一定要排查和解决问题。
3.GDB调试方法
3.1 方法一:PC安装ARM版本GDB,在PC端进行debug
3.1.1 在宿主机安装arm-linux-gdb
把gdb-7.7.1放到宿主机内解压,然后执行以下命令。
注意宿主机内置保留一套和目标机相关的arm-linux-gcc,否则可能会安装成其他平台的arm-linux-gdb
cd gdb-7.7.1
#target指明编译生成的GDB用于调试ARM-LINUX程序,prefix指明安装目录
./configure --target=arm-linux --prefix=/usr/local/arm-gdb -v
make
sudo make install
#在/etc/profile中增加
export PATH=$PATH:/usr/local/arm-gdb/bin
source /etc/profile
3.1.2 修改Makefile,增加如下选项
-g -Wl,-Map,test.map #添加在CFLAG后面 主要是-g,后面是用于生产map文件的
将编译后的可执行文件(如test)放置到目标机。
3.1.3 修改目标机以下文件
1./etc/profile
ulimit -c unlimited #2048
2.user.sh #找到一个开机自启动文件
echo "1" > /proc/sys/kernel/core_uses_pid
运行可执行文件,如下出现segmention fault ,会产生一个以core开头的文件
将 core.xxx 拷到宿主机,同时将可执行文件依赖的库文件放到宿主机指定路径下(如忽略此步骤定位的地方不准确,或者不能定位到问题)或者也可以在gdb调试core文件时指定库文件路径,然后在宿主机执行:
arm-linux-gdb test core.xxx
bt#会定位到程序出错的那几行
3.1.4 查看进程堆栈使用情况
cat /proc/pid/status
如使用量超过系统默认配置值8M,需增加目标机堆栈大小:
在/etc/profile文件增加以下内容
ulimit -s 102400 #100M
或
ulimit -s unlimited
3.2 方法二:在ARM端安装gdbserver,进行远程调试
3.2.1 编译器自带的gdbserver放到目标板
一般交叉编译已经自带了 gdb 和 gdbserver,因此可以不用移植。比如 arm-linux-gnueabihf-gcc 就自带了 gdbserver,路径为:/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin;
将 gdbserver 拷贝到开发板根文件系统的/bin 目录下。
3.2.2 VSCode+gdbserver 图形化调试
3.2.2.1 在.vscode 目录下新建一个名为“launch.json”的文件
3.2.2.2 修改launch.json 文件内容如下所示
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "cppdbg",
"request": "launch",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"miDebuggerPath":"/opt/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gdb",
"miDebuggerServerAddress": "192.168.1.251:2001",
"name": "test_arm.bin",
"program": "${workspaceFolder}/test_arm.bin",
/*"name": "test_pc.bin",
"program": "${workspaceFolder}/test_pc.bin",*/
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
]
}
3.2.2.3 在ARM板运行gdbserver 命令,等待PC连接
gdbserver 192.168.1.251:2001 test_arm.bin