打印
[应用方案]

内存溢出

[复制链接]
546|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
sanfuzi|  楼主 | 2024-7-17 13:12 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  • 现象: 最近在调试一个新的产品过程中,将电机调速由pwm占空比控制改为串口通信控制,移植基本的串口通信功能后,验证了新版硬件的串口收发都能正常工作,且电机功能未受到任何影响。随后在确认了通信协议后,编写添加相关通信代码,结果电机却无法运行,且再讲所有通信相关代码删除屏蔽后电机仍然无法工作;在与上一版本软件进行比较发现,所有电机相关程序未改变,只是添加了串口通信文件和通信校验的crc文件,且均已经屏蔽未使用;

  • 问题:
    电机不运行,仿真时程序有正常工作,但是所有变量无法置位或任何操作;
    所有电机相关程序未动,添加的相关代码和文件均已删除屏蔽

  • 分析解决:经过多方面查找,最后在map文件中发现xdata大小为3789(见图一),而根据数据手册xdata为2K,最大768bytes


    随后发现编译过程中xdata早就不知道什么时候超过了上限,原来是内存溢出,于是开始查找大数组,随后屏蔽了串口通信接收和发送的数据共80个字节,仍然无济于事;随后终于在添加的CRC文件中找到一堆大数组,将大数组屏蔽后问题解决;crc文件是为了与上位机保持一致校验采用了同事提供的文件,但是这份文件把所有crc的校验的计算法和查表法都汇集在一起了,当时确实没想太多就直接使用了;


上述简单的描述了问题解决的基本过程,但是实际操作过程中却没有那么顺利快速的想到这些,虽然我遵循自己一贯的解决思路顺利的找到并解决了问题,但是仍有几点心得需要牢记:

1.调试过程中如果添加大数组或者有大数组相关的文件,一定要关注当前芯片使用了多少内存和闪存,实际总共有多少内存和闪存,两者应该加强条件反射,便于提前发现问题;

2.由于我使用的MCU是51核且资源非常少,如果完全遵循常规的编程规范,减少全局变量使用,使用大量局部变量做函数封装,则会带来内存占用过多,所以在这种情况下要尽量使用全局变量完成模块之间的逻辑,可以采用结构体构建不同对象使用指针和地址访问来实现快速准确且不混乱的数据传递。

3.这次内存溢出还暴露出另一个问题,编译器为什么没有报警报错,一般我们在使用keil5创建调试工程时,默认是有设置内存大小的,如下图

但是在我调试的这个keil4工程中,并没有做相关设置

将芯片内存大小输入,

然后将屏蔽的大数组放开,编译报错如下

*** ERROR L107: ADDRESS SPACE OVERFLOW

所以在软件正确配置芯片资源后,是可以检测出这种问题的,这样就能及时发现问题,而不用白白浪费很多时间去查找。
此时问题虽然解决,但是内存却占用极大

因为我使用的是crc8查表法,所查的数组都是固定不需要修改的数据,所以在数组定义是加上code和const这两个关键字即可将数据存储在falsh上,且不可修改,这样大大减小了内存占用。

  • 思考总结虽然最终都能查到并解决了问题,但是想到一句古话:贵人不立围墙之下,同理:优秀的工程绝不仅仅是比别人更快的发现问题和解决问题,而且在项目开始的时候就会做好相对完善的准备,避免问题的发生,才是真正的高级。当然这不可能一蹴而就,离不开长期项目的积累和用心的总结。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

23

主题

3066

帖子

1

粉丝