【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
说到软件调试,有一点大家相信都有体会。那就是编写软件的时候,功能本身还是不算太复杂的。只需要前面流程、算法都设计好了,一般来说问题不大。但是调试软件的时候,特别是软件在客户现场崩溃的时候,这个时候就比较麻烦。所以一般情况下,我们要学会怎么调试嵌入式系统里面的软件bug,这是很重要的额一个技能。
就商业价值来说,软件架构设计、软件debug和软件调优是三个最为重要的技能。建议大家好好掌握一下,不断提高个人在这三个方面的价值。
1、使用gdb调试
gdb调试多是软件开发的时候进行的。目前树莓派4b上面是默认安装gdb调试软件的。因为编译工具也是在上面的,所以非常建议大家直接用它来进行软件开发和调试。和visual studio不同的是,大部分gdb调试都是用命令行进行的,这可能是大家唯一不习惯的地方。
2、使用coredump机制调试
对于那些低概率出现的问题,一般使用系统提供的coredump机制进行调试。还有一种故障特别麻烦,就是程序闪退,这种情况下,其他方法都不好使,能用的基本只有coredump了。后期,即使我们在家里复现出了对应的现象,但是本质原因是不是一样的,只有coredump才说的清楚。
在linux系统下面,使用coredump比较简单,首先输入ulimic -c unlimited,这样出现闪退的时候才会生成core文件。有了这个core文件之后,就可以配合刚才说到的gdb工具,进行进一步调试、分析原因了。怎么模拟出现闪退呢,其实最简单的就是下面两行代码,
int* p = 0;
*p = 0;
3、日志调试
日志调试是非常有用的方式,不仅仅是debug,在软件调优、接口对接等方面也发挥着巨大的作用。当然一些开源库,比如说boost,还有一些商业开发库,比如qt,也都提供了对应的日志输出方法,不过还是建议大家自己写一个log输出函数,这样以后不管使用什么平台,都可以用它来进行开发和调试。
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <iostream>
using namespace std;
FILE* selfLogFile = nullptr;
void customLog(const char* format, ...)
{
if (selfLogFile == nullptr) {
return;
}
time_t rawtime;
struct tm* timeinfo;
char timeBuffer[80];
time(&rawtime);
timeinfo = localtime(&rawtime);
strftime(timeBuffer, sizeof(timeBuffer), "%Y-%m-%d %H:%M:%S", timeinfo);
char message[256];
va_list args;
va_start(args, format);
vsnprintf(message, sizeof(message), format, args);
va_end(args);
fprintf(selfLogFile, "[%s] %s\n", timeBuffer, message);
fflush(selfLogFile);
}
int main(int argc, char* argv[])
{
selfLogFile = fopen("selfLog.log", "a");
if (selfLogFile == nullptr) {
return 1;
}
for (int i = 0; i < 5; ++i) {
customLog("Debug: Iteration %d", i);
}
fclose(selfLogFile);
return 0;
}
整个代码最主要的内容,就是这里的customLog函数,它首先获取时间,接着获取客户输入的字符串,最后将时间和字符串merge到一起,共同存储在selfLogFile里面。大家可以实际编译一下,看看效果。
4、另外一种日志生成方法
实际开发中,有的时候我们也会添加很多的std::cout打印。这个时候如果需要把它们转成log文件,其实只需要重定向一下即可,比如./process >> log.txt &。