为什么单片机上的程序不建议使用malloc?

这篇具有很好参考价值的文章主要介绍了为什么单片机上的程序不建议使用malloc?。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

做单片机研发前几年,一直没用过动态内存分配的功能,但是如果想成为软件架构设计师,这是绕不过的一道坎。

其实单片机很少使用c标准库自带的malloc()函数去动态分配内存,除非,你看老板不爽...

因为有缺陷,文章后面会提及。

一般是工程师借助现成的参考代码,然后重新设计内存管理代码,改进动态内存分配算法。

不过代码难度挺大,c语言功底不好的,看到代码会失声痛哭....

不信?我装个逼给你看!

下图,是以前自己借鉴(抄袭),再吃透,后改进的内存管理代码,测试已解决内存碎片问题。

为什么单片机上的程序不建议使用malloc?,单片机,stm32,嵌入式开发,嵌入式,c语言

为什么单片机上的程序不建议使用malloc?,单片机,stm32,嵌入式开发,嵌入式,c语言

代码没多少,却让我充分感受到,编程语言只是工具,编程思维才是灵魂

本来是计划用在无际单片机特训营项目6的,但是感觉太复杂了,怕老铁们学着学着来骂我,所以这代码就失宠了。

新手,或者有些一直从事比较简单产品的工程师,可能无法理解,malloc的应用场景,到底在哪里?

我以无际单片机特训营项目3来举例几个使用场景,或许你就明白了。

1.malloc使用场景1:动态任务创建

学过我们项目3的老铁,不知道有没有发现一个问题。

在用我们那个"小系统"创建任务的时候,不够灵活,每次增加新的任务,要手动在头文件增加任务ID

为什么单片机上的程序不建议使用malloc?,单片机,stm32,嵌入式开发,嵌入式,c语言

这样做的目的,是为了给下面这个任务结构体数组OS_Task,分配固定的内存空间。

为什么单片机上的程序不建议使用malloc?,单片机,stm32,嵌入式开发,嵌入式,c语言

最后才是创建任务。

为什么单片机上的程序不建议使用malloc?,单片机,stm32,嵌入式开发,嵌入式,c语言

如果使用动态内存分配,就可以省略前面步骤,直接创建任务,在任务创建函数里通过动态内存分配函数,给任务动态开辟一块内存,如果对RTOS有研究,应该知道我在讲什么..

2.malloc使用场景2:探测器列表

项目3是需要和不同的探测器(遥控器、门磁探测器、红外探测器、烟雾探测器等等)组网使用的。

我们做了一个菜单,在OLED屏上显示已经组网的探测器列表。

为什么单片机上的程序不建议使用malloc?,单片机,stm32,嵌入式开发,嵌入式,c语言

每个主机,已经组网的探测器数量都不一样,有些主机最多支持组网255个探测器。

每个探测器都有探测器ID、组网标志、序号、名称等参数。

为什么单片机上的程序不建议使用malloc?,单片机,stm32,嵌入式开发,嵌入式,c语言

那是不是意味着,如果主机最大支持255个探测器,如果没有动态内存分配,就要提前定义能够存储255个探测器参数的结构体数组?

事实上,我想到两种方式。

第一种是先存到外部的flash里,用到了再读出来,程序操作起来麻烦,而且效率慢,优点是省RAM。

第二种是直接分配255个探测器的静态存储空间,程序操作爽,效率高,但费RAM,还好特么用了STM32。

我这个探测器列表菜单,用的是第二种方式,因为我主机对探测器数量的上限设置是20个,哈哈。

为什么单片机上的程序不建议使用malloc?,单片机,stm32,嵌入式开发,嵌入式,c语言

对于这种功能需求,王炸的解决方案,就是用动态内存分配了!用时分配,用完释放!

但是,不建议直接用malloc()!!!

其实我第一次接触内存管理,是做蓝牙产品,用TI协议栈的时候。

当时有点奇怪的是,c语言标准库有malloc()动态内存分配和free()内存释放函数,osal系统为什么要自己写osal_mem_alloc()和osal_mem_free()?

直到后面自己做了一些复杂点的项目,自己也调过内存管理代码,才理解。

单片机上用malloc(),是个坑,有隐患。

我觉得内存碎片,是万恶之源。

malloc()函数本身只是动态分配内存,并没有直接解决内存碎片问题。

什么是内存碎片?

刚开始,我也不理解,什么是内存碎片,网上搜了很多相关内容,越绕越晕。

我尝试用通俗易懂的语言,长话短说,能不能理解,看基础和悟性了。

内存碎片分为两种:

1.外部碎片

想象一下,有一个大型的图书馆,图书馆的书架上摆满了各种各样的书籍,这些书籍大小可能不一样,书籍就像内存中的内存块(已被动态分配的内存),书架上的空位代表空闲内存(未被分配的内存或者被释放的内存)。

当读者借阅书籍后,书架上会留下一些空位。随着时间的推移,这些空位可能变得非常分散,就像散落在书架上的小块空间。

如果突然要存放一本很大很厚的书,到书架上时,可能很难找到足够大的连续空位来放置这本书。

那如果往后要存放的书,都是很大很厚的呢?

是不是虽然空位很多,但就是放不进去?那这块空间是不是就浪费掉了?

在内存分配时也是同理,如果频繁地用malloc()分配很多零散的内存块,每个内存块占用的字节数都不一样。

当这些内存块使用完,被free()释放以后,这块空闲内存,比如是8个字节,那下次,再有动态分配内存需求时,除非是8个字节或者以下才能使用这个内存块,如果是8个字节以上,这块内存块就相当于一直用不上,就浪费了。

所以说,即使总的空闲空间足够,但由于碎片化,也不好满足大内存块的分配请求。

这就是,在内存管理中,外部内存碎片化会导致系统无法为新的内存请求,分配足够的连续内存空间注意连续内存空间很重要,如果不连续,处理器就要不断从整个内存池去寻找,这样读取效率就会变低,这是内存碎片的影响。

2.内部碎片

内部内部碎片就是分配了内存空间,但未被使用的部分。

为此,我做了一个实验:

为什么单片机上的程序不建议使用malloc?,单片机,stm32,嵌入式开发,嵌入式,c语言

上图程序里,我给p1和p2分配1个字节内存,实际却分配了8个字节的空间,在释放前这7个字节都不能再被分配,相当于7个字节空间就浪费了。

以上两种碎片的产生,会让程序产生一种很尴尬的现象,就是明明有很多空闲内存,但总是分配失败,甚至导致程序死机,而且这种死机现象,通常是没有规律的。

印象中,我以前解决碎片问题的方法,大概是,内存释放后,把该内存块后面所有已分配的内存块往前迁移。

为什么单片机上的程序不建议使用malloc?,单片机,stm32,嵌入式开发,嵌入式,c语言

其实内存管理,就是开辟一个很大的数组,称内存池

为什么单片机上的程序不建议使用malloc?,单片机,stm32,嵌入式开发,嵌入式,c语言

然后后面所有的功能,比如动态内存分配,内存释放,都是基于这个大数组去完成,会涉及到数据结构,涉及到算法。

所以,数据结构和算法,这个时候针对性去学是最合适的

很多人项目都没做过,就去学,没什么鸟用,学完也不知道能干嘛。

说到这里,我相信你应该没有单片机上用malloc()的勇气了吧?

小批量生产可能测不出来,大批量生产就会陆续出现死机现象了,碰到了,就偷偷躲厕所里哭吧,这种问题能找死个人!

至于很多人说的,比如单片机不用malloc(),是因为内存资源有限,个人人为不是问题本质,一般能用上动态内存分配的产品,单片机内存资源都比较大。

本质就是用malloc()容易产生内存碎片,从而会引发一系列的问题,比如数据读取效率问题、稳定性问题等等...

PC上用malloc()估计也会存在内存碎片的问题,只是电脑内存动不动就上G,没有嵌入式设备这么敏感,当然PC可能还有别的方式去解决碎片化问题,这块我没做过,不做表态。

最后彩蛋时间,最近有粉丝问我怎么提升单片机编程思维和水平

我做了开发10几年,累计做过几十个项目,我针对这些项目共性功能,比如任务创建、管理、队列算法、LED特效、按键扫描等,写了一个标准程序框架。

为什么单片机上的程序不建议使用malloc?,单片机,stm32,嵌入式开发,嵌入式,c语言

这个架构,我在2019年也录了教程,我做新项目时,直接套用这个架构去写,效率直接起飞。

为什么单片机上的程序不建议使用malloc?,单片机,stm32,嵌入式开发,嵌入式,c语言

可以点击下方⬇️卡片看文章开头领取

《单片机入门到高级开挂学习路径(附教程+工具)》

《单片机入门到高级开挂学习路径(附教程+工具)》

《单片机入门到高级开挂学习路径(附教程+工具)》

或者可以找「无际单片机」全网同名的。文章来源地址https://www.toymoban.com/news/detail-837201.html

到了这里,关于为什么单片机上的程序不建议使用malloc?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 我为什么不建议使用框架默认的 DefaultMeterObservationHandler

    个人创作公约:本人声明创作的所有文章皆为自己原创,如果有参考任何文章的地方,会标注出来,如果有疏漏,欢迎大家批判。如果大家发现网上有抄袭本文章的,欢迎举报,并且积极向这个 github 仓库 提交 issue,谢谢支持~ 另外,本文为了避免抄袭,会在不影响阅读的情

    2024年01月21日
    浏览(55)
  • 代码的坏味道(二)——为什么建议使用模型来替换枚举?

    在设计模型时,我们经常会使用枚举来定义类型,比如说,一个员工类 Employee,他有职级,比如P6/P7。顺着这个思路,设计一个 Level 类型的枚举: 假设哪天悲催的打工人毕业了,需要计算赔偿金,简单算法赔偿金=工资*工龄 后来,随着这块业务逻辑的演进,其实公司是家具备

    2024年02月08日
    浏览(56)
  • 为什么 IDEA 建议去掉 StringBuilder,而要使用 “+” 拼接字符串?

    作者:京东零售 姜波 来源:京东云开发者社区 各位小伙伴在字符串拼接时应该都见过下面这种提示: 内容翻译:报告StringBuffer、StringBuilder或StringJoiner的任何用法,这些用法可以用单个java.lang.String串联来替换。使用字符串串联可以使代码更短、更简单。只有当得到的串联至

    2024年02月05日
    浏览(67)
  • Java面试题:为什么HashMap不建议使用对象作为Key?

    HashMap 是一种基于哈希表的动态数据结构,它允许使用任意不可变对象作为键(key)来存储和检索数据。然而,在某些情况下,使用对象作为 HashMap 的键可能会遇到一些问题。   首先,我们需要明确对象作为 HashMap 的键需要满足一些条件: 不可变性:对象的属性不能被修改,

    2024年04月22日
    浏览(55)
  • 为什么单片机可以直接烧录程序的原因是什么?

    单片机(Microcontroller)可以直接烧录程序的原因主要有以下几点: 集成性:单片机是一种高度集成的芯片,内部包含了处理器核心(CPU)、存储器(如闪存、EEPROM、RAM等)、输入/输出接口(如GPIO、UART、SPI、I2C等)以及时钟电路等功能模块。这种高度集成的设计使得单片机能

    2024年02月16日
    浏览(78)
  • Java开发手册中为什么不建议在for循环中使用“+“进行字符串操作

    java开发手册中对于循环体中进行字符串的拼接要求如下: 【推荐】循环体内,字符串的连接方式,使用 StringBuilder 的 append 方法进行扩展。 说明:下例中,反编译出的字节码文件显示每次循环都会 new 出一个 StringBuilder 对象,然后进行 append操作, 最后通过 toString 方法返回

    2024年02月08日
    浏览(55)
  • 定期为什么不建议自动转存

    自动转存是银行一种资金周转方式,一般是指用户的定期存款到期之后,银行可自动将到期的存款本息按相同存期一并转存的行为,在存款过程中,一般不建议投资者自动转存,其主要原因如下: 1、资金支配受到限制 如果是三年期存款,投资者选择存款时自动转存,则在存

    2024年02月12日
    浏览(45)
  • 为什么建议同时学多门编程语言

    晨读一本名叫《4点起床》的书,书中有一段描述与最近学习编制语言时自己的感受完全一致。算是一个小经验,分享给大家。 书中有一章的标题为《同时学六国语言记起来比较快》,其中有两段描述如下: 为什么我推荐大家同时学不同的语言呢?实不相瞒,我这几年在学西

    2024年02月10日
    浏览(80)
  • 为什么编程都建议不要用拼音命名

    我们看看知乎答主举的搞笑例子,一句话全部都是shi,表达起来确实困难。 上面这个回答,一句话全部都是“shi”,表达起来确实困难。并且让人误解 那么编程都建议不要用拼音命名,主要有以下原因: 可读性差 :使用拼音命名的变量、函数名等很难被其他人理解,特别是

    2024年02月04日
    浏览(82)
  • 你用过猿如意吗?猿如意可以使用ChatGPT哦,这里详细介绍了猿如意的功能,为什么我建议你使用猿如意,来看看吧

    你是否还在为为每次安装IDE(集成开发工具)要去各种网站找教程而烦恼? 你是否还在为各种文本格式转换而头痛? 你是否在为斗图都不过兄弟们而卑微? 你是否在为互联网中庞大冗杂却低效的教程文档而崩溃? 你想不想有一个关于代码的模板库? 你想不想不用\\\"科技\\\"就使

    2023年04月13日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包