摘要
在使用RT-Thread的过程中,发现RT-Thread SCons存在编译不稳定的问题。在源文件相同的情况下连续编译,相邻两次生成的map文件和bin文件差异巨大、运行效果不同,不利于版本回溯和管理。
本文主要总结了跟踪解决编译不稳定的问题的过程、经验、及Debug小技巧。
正文
1、怎么发现编译不稳定问题的?
Test1:发现同样的源代码编译生成的hex大小有差异。
在代码里多加一个int型变量,想观察新增变量对编译结果生成的text、data、bss、dec大小的影响,发现增加int变量前后观察到的现象与我理论分析的值不一样。
不改动代码,连续编译,发现在不改动源代码的情况下,编译生成的text、data、bss、dec大小也会有小幅度的变化。
因为代码能运行,不受编译结果的影响,所以决定暂不深入追究。
Test2:发现同样的源代码生成的BIN文件内容不同、运行结果不同,有的会卡死有的不会。
过了一段时间后,有一次,调试过程中发现代码卡死了,边改边调发现同样的代码有的时候能运行正常,有的时候会挂死。
联想到之前遇到一个问题:在编译优化等级为O3时会挂死,在编译优化等级为O1时能正常运行。
连着编译了4次,将4次编译生成的BIN文件存下来,分别烧录测试,就发现了会跑挂的BIN文件每次都会跑挂,不会挂的BIN文件每次都不会跑挂。
用文件对比工具对比两个BIN文件,发现有5000+的差异点;
为什么有必要解决编译不稳定问题?
同样的源代码,编译后生成了内容差异巨大、运行结果不同的BIN文件,相当于在编译过程中引入了随机变量,随机的BIN文件不利于版本管理、压测,也不利于用控制变量法解决发现的BUG(因为编译引入了新的变量)。
很明显,跟踪解决这个问题有利于保证软件质量,提高往后的调测效率。
编译不稳定问题的根本原因及解决方案?
根本原因:
SCons构建工具进行链接前会从文件系统中收集编译生成的目标文件(*.o, objects files)得到一个objects list。由于文件系统返回文件的顺序具有随机性,所以objects list中的目标文件排序具有随机性,导致最终链接出来的map文件具有随机性。
解决方案:
在SCons收集到objects list后,在objects list被转化为targe文件之前,对objects进行排序,排序顺序是sort函数的默认排序顺序。测试验证得,这样排序后编译正常、编译结果稳定、运行结果稳定,可作为解决方案。
编译tricks总结:
关于SCons指令的注意事项及几个有助于调试的指令:
一般使用指令的时候都会去找到官方的指令手册,然后对照着指令手册查自己想要的指令。但在RT-Thread里使用SCons指令时,不能完全参照SCons官网的手册,因为RT-Thread移植的SCons代码里对官方的源码做了封装,有的时候直接用官方指令是得不到官方文档所描述的指令效果的。RT-Thread的官方文档里最像指令手册的文档…目前只找到了RT-Thread工具手册,具体都有什么指令还需要结合RT-Thread的env源代码进行探索。
指令1,控制输出完整的编译指令
SCons -Q
SCons —verbose
参考链接:RT-Thread工具手册, SCons user guide:2.6, SCons user guide:9.2
指令2,控制输出一些调试解释信息
SCons —debug=explain
参考连接:SCons user guide:6.5
指令3,控制多线程编译(N为CPU核数)
SCons -jN
参考连接:RT-Thread工具手册,SCons user guide 10.1.3
可从map文件分析得到*.o文件大小的工具
Linux脚本与window脚本的一个区别:
Linux下的脚本是.sh,window下的脚本是.bat,.sh只需比.bat在开头加一行
#!/bin/bash
两个可以提效的gcc编译选项:
打开gcc所有的warning信息输出:CFLAG = -Wall
打开gcc warning信息的颜色:DFLAG = -fdiagnostics-color=always
debug常用思路总结:
解决BUG的一般思路即“猜想-验证”,常用的猜想及其验证思路有以下三种:
思路1:猜测BUG是由版本升级或Demo移植时引入的BUG。验证
步骤如下:
回退软件版本看BUG是从哪个版本引入的。
跟各种“正常”的Demo对比差异,看是否是这些差异点引入的BUG。
思路2:知道该BUG相关逻辑的理想情况,将实际情况与理想情况进行对比来找到答案。验证步骤如下:
梳理出从“源头”到“该BUG”的逻辑链,对逻辑链上的结点进行观测,看是哪一个结点引入的BUG
一般通过阅读源代码、做测试、加log、跟小伙伴交流等方式进行逻辑梳理。
思路3:跟小伙伴交流、脑暴,收集猜测和接下来可进行实验尝试测验的方向,试验收集到的点子、再交流收集点子、再试验收集点子……直到BUG被解决。
原作者:childerxxx