一种检测内存访问越界的方法

著录项
  • CN200610103263.0
  • 20060720
  • CN101110042
  • 20080123
  • 中兴通讯股份有限公司
  • 王国兵;刘晨吉;罗超
  • G06F9/50(2006.01)I
  • G06F9/50(2006.01)I G06F12/02(2006.01)I

  • 广东省深圳市南山区高新技术产业园科技南路中兴通讯大厦法律部
  • 中国,CN,广东(44)
  • 北京安信方达知识产权代理有限公司
  • 许志勇;颜涛
摘要
本发明公开了一种检测内存访问越界的方法,在应用程序使用从内存池中申请的内存块的过程中,检测是否存在内存写入越界的情况,包括主要步骤:在应用程序所申请内存块的前端增加申请该内存块的调用代码地址信息,尾端增加保护字和空闲区长度信息,同时在空闲区填充保护标记,当应用程序释放内存时,检测是否存在内存写入越界,并提示相关的异常信息,其中包括申请代码地址信息。本发明所述的方法对现有内存管理方法的改动很小,能很容易应用到现有的内存管理系统中,具有很强的实用性。
权利要求

1.一种检测内存访问越界的方法,在应用程序使用从内存池中申请 的内存块的过程中,检测是否存在内存写入越界的情况,其特征在于,包 括如下步骤:

(1)创建内存池时,如果初始化一个可用空间大小为Size的内存块, 则需要为其分配的全部内存空间为可用空间大小Size加上需要为该内存 块添加的前端信息和尾端信息所占空间大小之和,其中,所述尾端信息包 括保护字信息、空闲区长度信息;

(2)应用程序申请内存时,如果为其到一个合适的内存块,则将 所述内存块的尾端信息中的保护字设定为保护标记,将空闲区长度设定为 内存块大小Size减去用户申请大小的值,如果空闲区长度不为零,则在 从所述空闲区起始地址开始,在预设区域填充保护标记;

(3)应用程序释放内存时,检测尾端信息中的保护字是否为设定的 保护标记,如果不是,则提示内存访问越界的异常信息;如果保护字是设 定的保护标记,则检测空闲区中已填充保护标记的区域,当发现某处不是 设定的保护标记时,提示内存访问越界的异常信息。

2.如权利要求1所述的方法,其特征在于,步骤(1)中进一步包括: 所述前端信息包括头部信息、申请代码地址信息,所述内存块可用空间在 实际使用时分为用户数据区与空闲区;

步骤(2)中进一步包括:所述内存块的前端信息中填写头部信息, 并将申请代码地址设定为所获得的调用申请内存接口的代码地址;

步骤(3)中进一步包括:所述提示内存访问越界的异常信息中包括 申请代码地址信息。

3.如权利要求2所述的方法,其特征在于,所述步骤(2)中,如果 应用程序只有一个代码段,则在申请代码地址信息中只需记录偏移地址。

4.如权利要求2所述的方法,其特征在于,所述步骤(2)中,如果 应用程序包含多个代码段,则在申请代码地址信息中进一步记录代码的段 地址。

8.如权利要求2所述的方法,其特征在于,步骤(2)所述调用申请 内存接口的代码地址,通过一个接口函数获得,该接口函数当在某个函数 FuncA中调用时,其返回值为调用FuncA的代码的地址。

5.如权利要求1所述的方法,其特征在于,所述步骤(2)中,尾端 信息中的保护字设定的保护标记为特殊的不常见的数值。

6.如权利要求1所述的方法,其特征在于,所述步骤(2)中,在空 闲区中填充的保护标记为特殊的不常见的数值。

7.如权利要求1所述的方法,其特征在于,所述步骤(2)中,在空 闲区中填充保护标记的预定区域的长度,根据实际需要和策略确定。

说明书
技术领域

技术领域

本发明涉及一种检测内存访问越界的方法,具体地说,尤指嵌入式实 时系统中检测应用程序在使用所申请的内存块的过程中是否存在内存写 入越界的情况,并提示相关的异常信息。

背景技术

在嵌入式实时系统中,应用程序对内存的使用频率相当高,尤其是需 要频繁地申请和释放内存。而嵌入式实时操作系统提供的动态内存管理方 法是针对一般情况的,为应用程序提供内存申请和释放的接口,一方面, 调用这些接口的执行效率比较低,另一方面,频繁调用这些接口申请和释 放内存会形成过多的内存碎片,不仅影响执行效率,也造成内存浪费。

目前,在嵌入式实时系统中进行应用软件开发时,大多数情况下,会 在操作系统基础上形成适合自身需求的内存管理方法,对操作系统的内存 管理接口进行封装,提供给应用程序使用。这样的内存管理方法可能是多 种多样的,但一般具有一些基本的共同特征:首先通过一次或多次调用操 作系统的申请内存接口创建一个内存池,内存池由各种固定大小的内存块 组成,一般相同大小的内存块组成一个区域,通过链表或其它数据结构来 维护内存池;应用程序申请内存时,给其分配一个不小于所申请大小的可 用内存块。所分配的内存块往往大于所申请大小,内存块中超出申请大小 的部分为空闲区,应用程序不应该访问该区域。

应用程序申请到内存块后得到一个内存指针,通过该指针可以对内存 块区域进行读写操作。很多情况下,由于程序代码编写上的疏忽,会造成 内存访问越界问题,比如,写入时超出了所申请内存块的地址范围,覆盖 了其它内存区域,可能造成程序运行异常。有时,虽然没有超出内存块的 地址范围,但已超出了所申请大小,也就是覆盖了内存块中的空闲区,这 种情况不一定造成程序运行异常,但同样属于程序代码错误,如不及时发 现也是程序运行中的隐患。

现有技术中,为解决内存访问越界问题,试图实时检测出内存访问越 界情况,要求应用程序的内存访问操作都通过专门封装的接口进行,在接 口中对访问的内存地址和范围进行检查,进而判断是否存在访问越界。优 点是一定程度上能实时检测出内存越界情况,但是有如下缺点:首先,应 用程序对内存的读写操作都需要通过封装接口进行,必然会大大降低系统 运行效率,这对嵌入式实时系统来说是不可接受地;其次,应用程序对所 申请内存的使用方式是任意的,可以直接通过内存指针访问其中的地址, 也可以存放某种数据结构的数据,如果全部需要通过封装接口进行,会给 程序代码的编写造成极大的不便;最后,实现这种内存检测方法需要提供 专门的内存管理方法,不能将其方便地应用到其它内存管理方法中。

发明内容

本发明所要解决的技术问题在于提供一种检测内存访问越界的方法, 以解决内存访问越界问题,尤指嵌入式实时系统中检测应用程序在使用所 申请的内存块的过程中是否存在内存写入越界的情况,并提示相关的异常 信息。

为了解决上述问题,本发明提供了一种检测内存访问越界的方法,在 应用程序使用从内存池中申请的内存块的过程中,检测是否存在内存写入 越界的情况,其包括如下步骤:

(1)创建内存池时,如果初始化一个可用空间大小为Size的内存块, 则需要为其分配的全部内存空间为可用空间大小Size加上需要为该内存 块添加的前端信息和尾端信息所占空间大小之和,其中,所述尾端信息包 括保护字信息、空闲区长度信息;

(2)应用程序申请内存时,如果为其到一个合适的内存块,则将 所述内存块的尾端信息中的保护字设定为保护标记,将空闲区长度设定为 内存块大小Size减去用户申请大小的值,如果空闲区长度不为零,则在 从所述空闲区起始地址开始,在预设区域填充保护标记;

(3)应用程序释放内存时,检测尾端信息中的保护字是否为设定的 保护标记,如果不是,则提示内存访问越界的异常信息;如果保护字是设 定的保护标记,则检测空闲区中已填充保护标记的区域,当发现某处不是 设定的保护标记时,提示内存访问越界的异常信息。

进一步地,本发明所述的方法,其步骤(1)中进一步包括:所述前 端信息包括头部信息、申请代码地址信息,所述内存块可用空间在实际使 用时分为用户数据区与空闲区;

步骤(2)中进一步包括:所述内存块的前端信息中填写头部信息, 并将申请代码地址设定为所获得的调用申请内存接口的代码地址;

步骤(3)中进一步包括:所述提示内存访问越界的异常信息中包括 申请代码地址信息。

进一步地,其所述步骤(2)中,如果应用程序只有一个代码段,则 在申请代码地址信息中只需记录偏移地址;如果应用程序包含多个代码 段,则在申请代码地址信息中进一步记录代码的段地址。

进一步地,本发明所述的方法,其所述步骤(2)中,尾端信息中的 保护字设定的保护标记为特殊的不常见的数值;在空闲区中填充的保护标 记为特殊的不常见的数值;在空闲区中填充保护标记的预定区域的长度, 根据实际需要和策略确定。

本发明所述的方法,其进一步包括:

(4)根据所述提示内存访问越界的异常信息中包括的申请代码地址 信息,在程序代码中进行定位,确定所述内存块是在何处申请的,并进而 确定所述内存块使用过程中存在的写入越界情况。

进一步地,其步骤(2)所述调用申请内存接口的代码地址,通过一 个接口函数获得,该接口函数当在某个函数FuncA中调用时,其返回值 为调用FuncA的代码的地址;其所述接口函数根据堆栈中函数调用链, 向后回溯,取得调用FuncA函数时的返回地址,并将该返回地址作为 FuncA函数的调用代码地址。

本发明所述方法的出发点,不是实时检测内存访问越界情况,而是在 应用程序释放内存时检测该内存块的使用过程中是否存在内存写入越界 情况,完全不会影响现有内存管理系统中应用程序对内存的使用。本发明 所述方法不仅检查内存块尾部保护字,还检查空闲区,进行了非常完全的 检查;其次,本发明所述方法提示内存访问越界的异常信息时,包括了申 请代码地址信息,根据此信息在程序代码中可以进行定位,确定该内存块 是在何处申请的,进而分析确定内存块使用过程中存在的写入越界情况, 极大地方便了软件开发人员分析出代码中的问题。本发明所述的方法对现 有内存管理方法的改动很小,能很容易应用到现有的内存管理系统中,具 有很强的实用性。

附图说明

图1是本发明实施例所述的现有内存管理方法维护的内存块信息的 示意图;

图2是本发明实施例所述的内存块增加前端和尾端的保护信息后的 示意图。

具体实施方式

下面结合附图,对本发明实施例所述的技术方案作进一步的详细描 述。

如图1所示,现有的内存管理系统中,一般在内存块前端定义有前端 信息,用于管理和维护内存块,而在内存块后端不定义或很少定义尾端信 息,为实施例描述简单起见,后面描述中假设没有定义尾端信息,尽管如 此,本发明的方法同样适用于定义有尾端信息的内存管理方法。

如图2所示,本发明所述方法在现有前端信息的结构中增加申请代码 地址信息103。一般情况下,在嵌入式实时系统中,应用程序只有一个代 码段,因此只需记录偏移地址。如果应用程序包含多个代码段,则还需要 在申请代码地址信息中增加记录代码的段地址。为实施例描述简单起见, 后面描述中假设只有一个代码段。新的前端信息结构的C语言定义示例 为:

typedef struct tagHead

{

     .....0./*现有的头部信息成员*/

     unsigned long GetEIP;

}THead;

GetEIP的类型可根据CPU类型来确定,如上所述示例是在32位CPU 系统中的定义。

本发明所述的方法在内存块尾端增加尾端保护信息,包括保护字104 和空闲区长度105。结构定义示例为:

typedef struct tagTail

{

    unsigned long TailTag;

    unsigned short UnusedSize;

}TTail;

根据本发明所述增加的前端和尾端保护信息,创建内存池时,在现有 内存管理方法基础上需要作一定改动,具体方法如下:

(1)初始化一个可用空间大小为Size的内存块时,实际需要分配的 内存空间为THead大小、TTail大小和Size之和。

(2)将THead中GetEIP设定为0。

(3)将TTail中TailTag设定为MEM_TAIL_TAG(尾端保护标记), 将TTail中UnusedSize设定为0。MEM_TAIL_TAG为一较特殊的不常见 的数值,如0xFCFCFCFC等。

根据本发明所述的方法,申请内存接口需要在为应用程序分配的内存 块前端和尾端设定保护信息,步骤如下:

(1)假设应用程序所要申请的内存大小为UsedSize,实际为其分配 的内存块大小为Size(Size>=UsedSize)。

(2)调用获取当前函数调用代码地址的接口获取调用该申请内存接 口的代码地址(申请代码地址103),将THead中的GetEIP设定为申请 代码地址信息。关于获取当前函数调用代码地址的接口描述详见后文描 述。

(3)将TTail中TailTag设定为MEM_TAIL_TAG,UnusedSize设定 为Size-UsedSize。

(4)根据内存块头部信息地址和所申请大小UsedSize,计算出空闲 区102起始地址。根据UnsedSize以及实际情况需要,确定空闲区102中 的保护长度ProtectSize,比如,Debug版本中ProtectSize等于UnusedSize, 而Release版本中为提高效率,限制ProtectSize不能超过预定的最大值。 从空闲区102起始地址开始,将ProtectSize大小的内存区域中的每个字节 设定为MEM_UNUSED_TAG(空闲保护标记)。MEM_UNUSED_TAG 为一较特殊的不常见的数值,如0xFC等。

根据本发明所述的方法,释放内存接口需要根据尾端信息中保护字 104以及空闲区105来检测是否存在内存写入越界情况,步骤如下:

(1)根据输入参数中的内存指针可计算出内存块头部信息101地址, 一般根据头部信息101可取得内存块可用大小Size,再根据头部信息101 地址和内存可用大小Size计算出尾端信息地址。

(2)根据尾端信息地址读出尾端信息中保护字104,检查保护字104 是否是预先设定的值(MEM_TAIL_TAG),如果是,继续步骤(3),否 则提示内存访问越界的异常信息,其中包括从前端信息中获取的申请代码 地址GetEIP。

(3)根据尾端信息TTail中的UnusedSize,计算出空闲区102起始 地址,并根据申请内存接口中相同策略确定空闲区保护长度ProtectSize。 从空闲区102起始地址开始,逐个检查ProtectSize大小的区域中每个字节 的值是否是预先设定的值(MEM_UNUSED_TAG)。如果发现某个字节 的值不是MEM_UNUSED_TAG,则提示内存访问越界的异常信息,其中 包括从前端信息中获取的申请代码地址GetEIP。

根据本发明所述的方法,需要提供一个获取当前函数调用代码地址的 接口,其功能和实现描述如下:

设该接口函数名为GetEIPFunc,其功能是当GetEIPFunc在某个函数 FuncA中调用时,其返回值为调用FuncA的代码的地址。

其实现方法是根据堆栈中函数调用链,向后回溯,取得调用FuncA 函数时的返回地址,我们将此返回地址看作为FuncA函数的调用代码地 址。具体实现根据CPU类型和编译器的不同而有所不同。

上述具体实施方式以较佳实施例对本发明进行了说明,不应被视为对 本发明范围的限制。同样,根据本发明的技术方案及其较佳实施例的描述, 可以做出各种可能的等同改变或替换,而所有这些改变或替换都应属于本 发明权利要求的保护范围。

本文发布于:2024-09-25 11:16:55,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/2/85957.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议