嵌入式软件内存与指针相关问题

描述

  隐性的内存泄露问题

  内存泄漏(Memory Leak)是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。内存泄露是一个严重的慢性病,不会立即展现,但不知道未来的哪一天,所有的设备,会在相近的时间点爆发问题。

  内存泄漏还会导致系统意外的重启,重启的原因可能千奇百怪。因此,检测和解决内存泄漏,就显得非常重要。

  1. 泄漏的原因

  内存泄漏主要是发生在堆内存分配方式中,即malloc方式中,申请的内存没有得到释放,或者对应的指针被被覆盖,内存直接泄漏。因为内存泄漏属于程序运行中的问题,无法通过编译识别,主要在程序运行过程中来判别和诊断。

  2. 动态检测或监控是否内存泄露

  监控系统内存,周期性监控堆中可用内存的大小,是检测系统是否有内存泄漏的最有效的手段。系统的内存短期会随着业务数据的变化而变化,但长期来看,可用的剩余可用内存会围绕一个中轴线上下波动,如果存在内存泄漏,其剩余可用内存随随着时间的推移逐渐减少。

  3. 如何找到在哪儿内存泄露

  可以使用工具检测代码中有没有静态的内存泄露,也可以在代码中增加标记,检测长期未释放的堆是谁申请的,在代码中查找。可以参考文章《动态内存管理及防御性编程》。

  指针跑飞的问题

  指针跑飞就是指针指向不正确的位置,指针未初始化或数组/指针越界访问,导致系统崩溃。

  指针跑飞是常见的问题,问题很严重,但解决起来其实并不难,指针跑飞系统crash时,如果平台软件会打印出函数调用栈、segment fault错误、代码出错的地方、coredump文件等信息。有了这些信息,再分析源代码,其实是很容发现或找出当前代码中指针跑飞的原因的。

  如果基于第三方的SDK开发,指针跑飞直接就重启,可能不会有任何提示,因此,最好能够在编码时就能够提前预防,而不是等待程序跑飞之后再定位解决 。

  常见的手段:

  1、熟悉和遵守代码编写规范,加强代码的评审,把问题消灭在编码阶段。

  2、静态检测工具对代码进行检测。

  3、增加边界性测试用例,一般指针异常是在边界或异常情形下发生的。

  4、增加异常场景的测试,异常场景是违反常规的测试场景,这些异常业务场景,能够尽早shi发现隐藏的问题。

  空指针的问题

  空指针是“指针跑飞”的一种特殊情况,即指针为NULL,通常出现在指针用NULL值初始化后,在某些情况下没有给指针赋值,就直接使用指针范围内存。或者接收函数返回的指针变量,忽略了函数返回NULL的情形。

  在使用指针前,检查指针是否为空,如果为空,在代码中执行异常处理流程,如打印出错信息,或者ASSERT,这样就可以避免引起更严重的问题,相对来说多使用一个if即可规避。

  栈溢出导致的问题

  栈溢出时会访问不存在的RAM空间,造成代码跑飞,这时无法得到溢出时的上下文数据,也无法对后续的程序修改提供有用信息。

  函数递归调用,系统要在栈中不断保存函数调用时的现场和产生的变量,如果递归调用太深,就会造成栈溢出。函数内局部数组变量的内存空间过大,或者局部数组变量的下标范围溢出,破坏了栈空间中的内容。这种问题容易解决但初始不容易查到原因。如果是带操作系统的,一般系统内核会直接提示栈空间不足,将任务栈空间加大,或者不静态分配,用malloc动态创建,从堆中分配的。平时编码中禁止使用循环递归函数。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分