0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Windows CE中的内存泄漏问题

嵌入式应用开发 来源:嵌入式应用开发 作者:嵌入式应用开发 2022-08-15 09:47 次阅读

很多实时嵌入式设备是长时间不间断运行的,即使是少许的内存泄漏,也会积少成多,对嵌入式系统带来灾难性的影响。这几天,我在嵌入式软件项目中就饱尝到这个痛苦,让我明白到嵌入式实时系统的应用软件也会有许多内存问题,从而导致嵌入式系统的崩溃。例如非法的内存访问、各种死锁以及诸如堆栈溢出、数组越界和内存泄漏等

Windows CE作为最流行的一种嵌入式操作系统,现正广泛被应用。我所负责的嵌入式应用程序也是在Windows CE平台上开发的。在进入测试阶段中,我发现有一个程序模块系统内存和CPU资源消耗急剧增加,持续增长到出现OutOfMemoryError为止,然后自动重启。这个问题折腾到我生不如死,痛苦不堪。花了我好几个通宵达旦的加班后,经过分析终于确认Windows CE内存泄漏是造成这次Windows CE系统崩溃的主要原因。这里与大家分享我在开发过程中遇到的内存泄漏的检测和处理解决过程。

一.Windows CE如何进行内存分配?

为了判断是否有内存泄露,我们首先需要了解Windows CE是如何管理内存的。许多嵌入式程序员都有一个共识,就是如果评选在Windows CE 程序中遇到最多的问题,那其中一个问题一定有内存问题。

(1)什么是Windows CE内存管理

一般来说,运行Windows CE的嵌入式设备出于紧凑型的考虑内存都不大,以至于有时候有些程序员会为了节省内存开支而牺牲程序的某些性能。但尽管WinCE系统的内存很小,用来管理内存的函数却十分完善。Windows CE实现了Windows XP中几乎全部的Win32内存管理API。例如,Windows CE支持虚拟内存分配,本地和分离的堆管理,甚至还有内存映射文件。像Windows XP一样,Windows CE支持带有应用程序间内存保护功能的32位地址空间,这一点对于多程序和多线程运行时是非常重要的功能。但是Windows CE毕竟是被设计来应用于实时场合的,所以它底层的内存结构又不同于Windows XP。

Windows CE内核可以在Flash上直接运行,也可以加载到内存中运行。Flash的运行方式,是把内核的可执行映像烧写到Flash上,系统启动时从Flash的某个地址开始执行。在这种情况下,Windows CE系统就像直接读硬盘,存储在Flash上的程序能够以现场执行的方式运行。这种能力对小型系统来说使之在具有巨大的优势,这样这能快速启动一个应用程序,因此这种方法被很多嵌入式系统所采用。另一种是内核加载方式,是把内核的压缩文件存放在Flash上,系统启动时读取压缩文件在内存里解压,然后开始执行。

(2)虚拟内存和函数应用

和大多数现代操作系统一样,Windows CE实现按需调页的虚拟内存机制。由于Windows CE系统使用了虚拟内存,这就给应用程序造成了一个假象,以为计算机安装的内存远远超过自己所需要的数量。Windows CE是32位的操作系统,因此支持4GB的虚拟地址空间。Windows把这些地址空间分给进程和系统使用,每个部分可以获得2GB的虚拟内存。

虚拟内存是内存类型中最基础的。Windows CE 实现了系统的虚拟内存管理,在一个虚拟内存系统中,应用程序主要处理这个虚拟的地址空间,并不涉及到由硬件管理的物理内存。系统调用虚拟内存API来为其它类型内存分配内存,包括堆和栈。Windows CE虚拟内存页可以处在三种状态:自由(free),保留(reserved),或被提交(committed)。

简单说,就是当一个应用程序要查询系统的内存时,可使用虚拟内存API,包括VirtualAlloc,VirtualFree和VirtualReSize函数,这些函数可以直接操作虚拟内存空间的虚拟内存页面。例如,页面可以保留,提交给物理内存,或使用这些函数释放。Windows CE实现了Win32的GetSystemInfo和GlobalMemoryStatus函数。另一个检测系统状态的函数是:void GlobalMemoryStatus(LPMEMORYSTATUS lpmst),通过GlobalMemoryStatus返回的信息可以验证Windows CE内存结构。

(3)释放虚拟内存

不同于Windows XP,Windows CE只支持在堆中分配固定(fixed)的块。这简化了内存块在堆中的处理,但是这使得堆在分配和释放一段时间后会产生碎片。当堆里已经清空的时候,仍然会占用大量的虚拟内存页,因为系统不能在堆中内存页没有完全释放的时候回收这些页。这时,一般情况下是可以通过调用VirtualFree来取消提交,或释放虚拟内存。从物理RAM页中取消提交或者取消映射,但是保持页被保留的状态,当在区域中的所有的页通过VirtualFree被释放时,也应该处在同样的情况下。更确切地说,区域中的全部页要被释放,那这些页要么都是被提交的页,要么都是被保留的页。如果有些页被提交,有些页被保留,那么VirtualFree函数调用就会失败。

实际上,Windows CE会监视系统自由的内存,并对越来越少的内存作出响应。当很少内存可用时,Windows CE首先发送WM_HIBERNATE消息,接下来会限制可能的内存分配。当应用程序被发送了一个WM_HIBERNATE消息后,系统将检测内存级别,确认是否可用内存在限度之上,如果可用内存不足,WM_HIBERNATE消息将被发送给下一个程序,这会持续到所有程序被发送了WM_HIBERNATE消息。

二. 什么是内存泄露

Win32编程中常见内存错误:①内存分配错误;②使用未初始化的内存;③内存泄露;④使用已经释放的内存资源。

poYBAGL5pPWACkyiAADQEXbnnQk566.png

(1)什么是内存泄漏

内存泄漏是指程序在运行过程中申请的内存,在程序结束时没有被释放。我们常说的内存泄漏是指堆内存的泄漏,堆内存是指程序从堆中分配的。一般来说,应用程序是使用从堆中分配到一块内存,使用完后程序必须负责相应的释放该内存块。否则,这块内存就不能被再次使用,我们就说这块内存泄漏了。

一般来说,在所有时刻Windows CE内存管理器都知道进程所拥有的物理内存和虚拟内存。然而,如果进程分配内存时但由于Bug而无法释放内存(内存泄漏),内存管理器就可能无法了解这些已分配的内存,也无法重新访问这些内存,而必须等到进程退出时回收内存。但需要特别注意的是,同样的程序在Window XP平台上可能没有什么问题,但在缺乏内存的Windows CE平台,经过长时间运行该程序可能会内存耗尽而导致系统重启,这是我在经过几个生不如死的通宵达旦测试后得到的宝贵经验和教训。

因此,内存泄漏引发的性能失常完全不同于程序错误,这些问题很难通过调试器对代码进行单步调试加以解决。对于将会在某时刻退出的桌面应用程序,较小的内存泄漏是可以承受的,因为退出进程将把占用的所有内存返还给操作系统。但对于长时间运行的嵌入式系统,则通常需要确保绝对没有内存泄漏。

(2)常见的内存泄漏原因

常见的内存泄漏有这几种原因:①Windows CE内存碎片。②在局部堆申请的堆只增加不会马上减少,直到程序退出。③程序运行时分配物理内存,当程序使用完后,这些物理内存仍然被占用,直到系统内存不足时分页内存交换到分页文件中,然后才释放掉其占用的物理内存。④Windows CE内存管理的缺陷。

总而言之,内存泄漏产生的主要原因是保留了却不再使用的内存空间。Windows CE虽然有自动管理内存的功能,但内存泄漏也是不容忽视,它往往是破坏嵌入式系统稳定性的重要因素。

三. 如何检测和处理内存泄漏?

如何查找引起内存泄漏的原因,一般有两个步骤:第一是安排有经验的编程人员对代码进行走查和分析,找出内存泄漏发生的位置。第二是使用专门的内存泄漏测试工具进行测试。

(1)代码走读检测内存泄漏

通常在怀疑发生内存泄漏之后,第一步是要弄清楚泄漏了什么数据和引起了什么泄漏。一般说来,一个正常的系统在其运行稳定后其内存的占用量是基本稳定的,不应该是无限制的增长的。根据这样的基本假设,我们持续地观察系统运行时使用的内存的大小,如果内存的大小持续地增长,则说明系统存在内存泄漏。

内存泄漏可通过代码走读来发现和定位,也可以用专用的工具来测试和定位。实际上,对于内存泄漏,代码检查有时能比采用任何技术解决方案更快地找到问题所在。预防内存泄漏的唯一方法就是要求程序员在程序结束时,必须将每个申请的内存都释放。

(2)使用工具检测内存泄漏

一旦知道确实发生了内存泄漏,就需要更专业的工具来查明为什么会发生泄漏。在这个时候,我们通常需要使用一些开销较低的工具来监控和查找内存泄漏。查找内存泄漏的工具很多,最常用的释放工具就是dmalloc和mpatrol,这些工具提供了记录并检查所有内存分配的调试版堆栈,从而有利于分析内存泄漏和悬挂指针。

检测内存泄漏的关键是要能截获住对分配内存和释放内存的函数的调用,当截获住这两个函数,我们就能跟踪每一块内存的生命周期。比如,每当成功的分配一块内存后,就把它的指针加入一个全局的list中;每当释放一块内存,再把它的指针从list中删除。这样,当程序结束的时候,list中剩余的指针就是指向那些没有被释放的内存。哪么,最简单的内存泄漏检测方式就是截获住这些指针。

审核编辑:汤梓红

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

    关注

    5068

    文章

    19008

    浏览量

    302916
  • WINDOWS
    +关注

    关注

    3

    文章

    3524

    浏览量

    88398
  • 内存泄漏
    +关注

    关注

    0

    文章

    39

    浏览量

    9204
收藏 人收藏

    评论

    相关推荐

    Windows CEWindows 2000/XP有什么区别?

    Windows系统。它使用平面内存模式寻址,可以同时运行多个程序并支持一个程序的多个线程,并且非常精炼,只有很小的内存要求。
    发表于 10-15 08:10

    Windows CE板卡支持包介绍

    Windows CE板卡支持包用于netX的Windows CE 镜像带有一个周期为120天的免费测试版。板卡支持包需要通过专用的驱动创建自己的镜像。其中包括
    发表于 04-11 08:50 27次下载

    基于Windows CE嵌入式系统的智能小区广告机的设计

    Windows CE 是微软公司专门为嵌入式市场设计,为快速建立下一代小内存占用的设备提供的一个健壮的实时操作系统。Windows CE
    发表于 08-18 10:15 19次下载

    ARM嵌入式WINDOWS CE实践教程

    ARM嵌入式WINDOWS CE实践教程 安装WINDOWS CE 4.2本节讲述如何安装Windows
    发表于 03-01 15:45 81次下载

    Windows CE .NET 常见问题与解答

    Windows CE .NET 常见问题与解答 1. Microsoft Windows ® CE .NET®是什么?Microsoft
    发表于 07-07 10:09 1526次阅读
    <b class='flag-5'>Windows</b> <b class='flag-5'>CE</b> .NET 常见问题与解答

    Windows CE简介、特点及应用

    Windows CE简介、特点及应用 一、Windows CE简介  
    发表于 01-11 08:43 3974次阅读

    Windows CE详解

    从纯粹软件技术的角度看 Windows CE ,则可以说Windows CE就是嵌入式的Windows,虽然
    发表于 06-09 15:51 67次下载

    Windows CE下实现串口通信

    文章首先简单介绍了在WIndows CE下设备驱动程序的访问 方式, 然后详细介绍了在WIndows CE下实现串口通信的方法和过程。
    发表于 04-18 14:12 6次下载

    Windows CE 进程、线程和内存管理三

    三、内存管理 同其它Windows操作系统一样,Windows CE.NET也支持32位虚拟内存机制、按需分配
    发表于 11-08 10:30 0次下载
    <b class='flag-5'>Windows</b> <b class='flag-5'>CE</b> 进程、线程和<b class='flag-5'>内存</b>管理三

    内存泄漏的特点和类型

    在计算机科学内存泄漏(memory leak)指由于疏忽或错误使程序未能释放而造成不能再使用的内存的情况。内存
    的头像 发表于 06-20 10:58 2787次阅读

    什么是内存泄漏内存泄漏有哪些现象

    内存泄漏几乎是很难避免的,不管是老手还是新手,都存在这个问题,甚至 Windows 与 Linux 这类系统软件也或多或少存在着内存泄漏
    的头像 发表于 09-05 17:24 9599次阅读

    怎么解决C语言中的内存泄漏问题呢?

    只有在堆内存里面才会发生内存泄漏的问题,在栈内存不会发生内存
    发表于 06-11 17:31 560次阅读
    怎么解决C语言中的<b class='flag-5'>内存</b><b class='flag-5'>泄漏</b>问题呢?

    什么是内存泄漏?如何避免JavaScript内存泄漏

    JavaScript 代码中常见的内存泄漏的常见来源: 研究内存泄漏问题就相当于寻找符合垃圾回收机制的编程方式,有效避免对象引用的问题。
    发表于 10-27 11:30 358次阅读
    什么是<b class='flag-5'>内存</b><b class='flag-5'>泄漏</b>?如何避免JavaScript<b class='flag-5'>内存</b><b class='flag-5'>泄漏</b>

    线程内存泄漏问题的定位

    记录一个关于线程内存泄漏问题的定位过程,以及过程的收获。 1. 初步定位 是否存在内存泄漏:想到内存
    的头像 发表于 11-13 11:38 579次阅读
    线程<b class='flag-5'>内存</b><b class='flag-5'>泄漏</b>问题的定位

    C语言内存泄漏问题原理

    内存泄漏问题只有在使用堆内存的时候才会出现,栈内存不存在内存泄漏问题,因为栈
    发表于 03-19 11:38 477次阅读
    C语言<b class='flag-5'>内存</b><b class='flag-5'>泄漏</b>问题原理