遇到的bug汇总-初学者的Bug List!
作为一个能力不足的人,在日常生活中,总会有那么一些bug让我难以接受。我将其中的部分汇总如下,聊以慰藉。
本文理论上是长期更新的,不要嫌文章短(
时间流逝造成的未知错误
PowerToys 的bug
作为Vim用户,交换Caps Lock和Esc键是常规操作了。为了体现Geek风范,我使用了 MicroSoft维护的PowerToys来实现键盘重映射。
但是,我没有想到的是,当前版本的PowerToys存在假死的情况。假死过后,会强制软件激活Caps Lock,造成我编码的误操作。令人惊奇的是,激活的Caps Lock,我需要按两次才能取消。第一次是硬件激活,第二次是硬件取消。可以算是步调不一致了。
“-target”? 你从哪里来?
先前在调试clang的时候,在系统变量中添加了CXXFLAGS
和它的值 -target XXXX
。后来因为clang 始终无法测试成功,便卸载了clang。但是,系统变量没有被删除。
后来,我再调试CMake的时候,无论怎么make都会显示无法通过编译器测试,显示Uknown command line "-target"
。
我怎么想,都觉得不可思议。明明g++使用格式为--target
,为什么CMake会这么不合常理地使用这样的编译选项,反而告诉我无法编译呢?
可想而知,耗费三个小时后,我灵光一闪,删除了系统变量中的CXXFLAGS
。编译通过了。
所以clang和g++读取同一个系统变量,这种原因我不得而知。
关我Anaconda何事?
首次使用VSCode编辑Qt6生成的CMake工程时,Intelligence总是提示错误的引用。仔细一看,include到了Anaconda/Library/Qt
里面的文件。这就问题很大了。
思索再三,我发现VSCode的C/C++
扩展中对include path的定义,是先在系统环境变量中搜索的。那么,Anaconda的路径在Qt之前,便会直接从Anaconda中include,这就产生了错误。
将环境变量的顺序调整了之后,问题不再复现。
编程技术造成的错误
C语言篇
忘记加括号
1 |
|
这样的代码会将任何angle输入,变成0的。因为uint16_t的作用对象错了,应该是整个表达式的值。表达式的类型是double,在进行计算的时候精度损失可以忽略。但是uint16_t位置不对,提前变换成了整型,这不是胡闹吗?
正确修改如下。
1 |
|
volatile?并行计算需要好好学习
多次读取一个变化的值,读出来的竟然是相同的。这是正常现象,编译器做出来的优化,只需要加上volatile关键词即可。问题的根本在于并行计算理解不够,有待更加深入学习并行计算理论了。
造轮子是需要水平的,溢出是需要检查的
课程要求我手动造轮子。可惜能力不足,出现了内存溢出。但是我怎么检查,怎么测试,都不可能出现溢出啊?最后发现,是没有赋初始值造成的数据错乱,而不是指向了释放的内存空间。所以,造轮子需谨慎,我仍然是一个菜鸡。
CMake篇
“默认化的默认构造函数不能为constexpr”
首次尝试利用Qt Creator生成mingw工程并利用Visual Studio 2022调试时,就连最基本的代码都无法编译通过。报错就是标题内容,尽管是自动生成的代码。仔细检查后 发现,Visual Studio读取CMake文件时,没有读取到正确的CMake生成器,默认使用了Ninja,这个我可不会。
在VS的某个界面中,修改CMake工程的生成器,为Unix Makefiles,这样就编译通过了。
C++篇
vector数据存储在哪
在阅读OpenGL教程时,发现了如下语句。
1 |
|
这时发现vector被当成了数组使用。但是记得vector是特殊的结构,不能直接读取才对,怎么回事?
这是因为vector本身的存储结构是特殊的,但是对于数据的存储位置来说,数据始终是连续的。这也保证了vector是可以随机读写的。
1 |
|
通病
无后效性提醒
在一次编程实践中,我发现系统出现了不应该的异常抖动。代码如下。
1 |
|
测试的时候,出现了异常的速度抖动,方向频繁切换。但是,使用如下代码就可以解决。
1 |
|
需要我写两遍?
不,真正的原因是,代码中的x = -x; y = -y;
具有后效性,将速度反向放在这个地方没有任何道理,只会造成相同调用条件产生反向的输出结果。将这两行代码删除后,问题得到解决。
也许单看这个解释读者仍然不能理解。那么看下面的一个使用案例。
1 |
|
周期调用这个函数会发生什么?流程大概是这样的
1 |
|
看到了吗?它的数据在震荡!
硬件设计中出现的问题
程序设计
中断函数提高速度
中断函数中一定不能写延时,中断函数的速度也需要尽可能提高。如果出现了中断重叠,可能会产生意料之外的错误。例如部分外设频繁死机之类,不容易检查的。
外设错误调用
STM32中外设的使用需要提前配置。不仅如此,如果外设配置了某一种调用模式,而你却采用了另一种模式调用,也会出现严重问题,比如,卡死HardFault
。举个例子,如果你外设没有配置DMA,或者配置DMA之后使用了阻塞模式,那么,当你下一次尝试使用DMA模式时,会进入HardFault
。
接线错误
“target dll canceled”
通常来说,STM32的调试SWD位于PA13,PA14。由于PCB绘制过程中,出现了与USART1接口相邻的情况,接线同学在接线时,误将串口线接在了PA14上。所以,无法进行任何烧写动作了。任何操作都会显示无法连接。
重新将串口线接在USART1的接线柱上,问题得到解决。
异常现象
未知重启
2021年10月1日的一次调试中,STM32芯片出现了多次的异常重启。经过分析,一共有两种原因,二者交替触发,造成问题难以定位。这两种原因分别是内存泄漏单片机挂起重启,和电压不稳芯片重启。
正常情况下,内存泄漏应该进入HardFault中断中阻塞全部程序。但本次实验中,STM32在遍历了全部内存空间后,产生了某种异常,形成了软件重启。表现为调试串口信号从起始位置重新开始。
在之后的实验中,出现了杜邦线端口松动,电压断供的情况。表现为调试串口信号乱码,且代码从头开始执行。
本人根据调试串口信号的复位信息得到了上述两种复位方式。在修复了相应漏洞后,程序恢复正常,
晶振不起振
目前遇到的晶振无法起振问题,主要有三种原因。
第一种原因是多次拆焊造成晶振内部结构受损。第二种原因是QFN封装造成的焊盘未连接。第三种原因是气温问题,造成芯片HSI和HSE偏差过大,芯片自检不通过无法起振,或者晶振无法起振。
芯片不正常使用
LDO篇
通常在使用LDO的时候,会用到一颗进行5V->3.3V
的芯片。而在调试的时候,通常会使用3.3V供电,这样MCU通电工作,而其他芯片可以保持较低的水平。但是有的时候会忘记这一点,从而调试时发现其他芯片不能正常工作。比如轨降较大的运放,就会出现直接饱和的现象。
运放篇
通常买的的便宜运放都不是轨到轨的。在LDO篇中提到了,调试供电情况下,5V获得的反相电压通常只有2.5V,那么放到运放上,饱和电压就只有1.3V了。这显然会产生很大的测量误差。应当铭记这一点。
官方出现的问题
STM32CubeMX已知问题
CubeMX生成的HAL库文件出现的问题,多半是顺序问题。
这里推荐今后使用assert
,方便排查ST自己的问题。因为我已经多次被ST坑到。
I2C异常现象
代码
1 |
|
需要在I2C
初始化之前完成。而生成的代码中,该函数通常在函数末尾。这就会造成初始化失败,无法通信。
DMA初始化失败
代码
1 |
|
必须在调用DMA的外设初始化之前完成。而CubeMX的初始化顺序和CubeMX配置顺序
有关,而不是逻辑顺序
或者依赖关系
。在这一点上,早在20年便有人指出这样的错误。直到今天(2022年3月13日)ST依然没有改正这个错误。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!