当前,绝大多数嵌入式平台上的软件都采用C语言编写。除了代码简洁、运行高效之外,灵活操作内存的能力更是C语言的重要特色。然而,不恰当的内存操作通常也是错误的根源之一。如“内存泄漏” ——不能正确地释放已分配的动态内存,就是一种非常难于检测的存错误。持续的内存泄漏会使程序性能下降到最终完全不能运行,进而影响到所有其它有动态内存需求的程序,在某些相对简单的嵌入式平台上甚至会妨碍操作系统的运转。再如“写内存越界”,一种不合法的写内存操作,极可能破坏到本程序中正在使用的其它数据,严重的时候还可能对其它正在运行的程序甚至整个系统造成影响。为此,本文介绍一个增强的、可定制的动态内存管理模块(以下不妨简称Fense),在 C语言提供的内存分配函数基础上,增加了对动态内存的管理功能;能记录软件运行过程中出现的内存泄漏信息,同时也具一定的监测内存操作的能力;可以发现绝大多数对动态内存的写越界错误。
; 1 Fense的设计原理
Fense 通过设立一个双向链表(struct Head *stHead)来保存所有被分配的动态内存块的信息。链表中的每个节点对应一个动态内存块,节点中包括此内存大小、分配发生时所在的源文件名和行号以及被释放的时候,Fense又从st_Head中删除之,检查st_Head中的节点即可得到未被释放的本节点的数值校验和等。Fense将每一个分配的动态内存块插入到链表st_Head中;当此内存放内存块信息。链表节点结构定义如下:
struct Head{
char file; /分配所在源文件名*/
unsigned long line;
size_t size;
int checksum;
struct Head prev,next;
};
struct Head *st_Head=NULL;
为了检测写越界的错误,Fense在用户申请的内存前后各增加了一定大小的内存作为监测区域,并初始化成预定值。这样,当程序发生越界写操作时,预定值就会发生改变,Fense即可检测到错误。
通过Fense分配到的动态内存结构如图1所示。由此可知,Fense_Malloc(Fense的内存分配函数)返回给用户的指针ptr指向的是用户申请内存区域的起始位置。链表节点、前/后监测区域均为Fense内部使用,是用户不可见的。
动态内存结构
2 用户定制选项
Fense有5组宏定义提供给用户对功能进行定制。各组选项控制意义如下:
WARN_ON_ZERO_MALLOC 用户申请零分配空间时警告信息;
FILL_ON_MALLOC 分配时初始化内存块;
FILL_ON_MALLOC_VAL 分配初始化时的预设值;
FILL_ON_FREE 释放时填充内存块;
FILL_ON_FREE_VAL 释放时填充内存块的预设值。
以上4个选项的主要功能是初始化刚分配到的内存和刚被释放的内存为预设值,尽可能地避免出现因使用未初始经的内存而引发的错误。
FENSE_FRONT_SIZE 定义前监测区域大小;
FENSE_FRONT_VAL 定义前监测区域的预设值;
FENSE_END_SIZE 定义后监测区域大小;
FENSE_END_VAL 定义后监测工域的预设值。
在Fense 工作过程中,对内存越界写操作的检验是通过比较监测区域的当前值与本监测区域的预设值来确定的。显然不能排除这样一种可能:即发生在监测区域的越界写操
作写入的数值与监测区域的预设值恰好相同,此时,Fense无法发现错误的发生。对于这种情况,用户可以通过更改监测区域预设值(FENSE_FRONT_VAL和FENSE_END_VAL)和监测区域大小(FENSE_FRONT_SIZE和FENSE_END_SIZE)为多组不同的值来反复测试,这样就可以大幅度地提高监测的准确性。
VALIDATE_FREE ,free是检查本内存块是否在链表中;
CHECK_ALL_MEMORY_ON_FREE ,free时检查链表中的所有内存块。
由于存在这样一种情况:对内存块A的写操作出现了越界错误,写到了另一内存块B的区域内。此时,仅仅检查内存块A的有效性就无法发现问题,如果同时检查所有的动态内存块,则有可能发现错误所在。以上选项即为此而设。
1794-IE8
1794-TB2
1794-TB3
1794-TB32
IC200ALG240
IC200ALG320
IC200EBI001
IC200ERM002
IC200MDL241
IC200MDL742
IC200PWR102
T5N400 R320
3500/22M
3500/42M
3500/53
9200-01-05-10-00
1756-CNB/E
1756-ENBT/A
1756-L61
1756-PA75
140CPU43412U
990NAD23000
UP1161
EI813F
F1830F
TU810V1
TU812V1
8509C
1757-SRM
22A-B4P5N104
MDV60A0110-5A3-4-00
MDD112D-N-030-N2M-130GA0
A06B-0075-B503
A06B-6078-K811/L-13M
A06B-6127-H103
A06B-6151-H045#H580
SPEED REGULATOR MAX SPEED 2
TSX08CD08R6AS
UGRMEM-02SNQ33 TG-7SVE
1FT5071-0AF71-1
1FT5102-0AG71-1
MAD130D-0200-SA-M0-AG0-05-N1
6EV3054-OFC
FBM201
FBM201
395
1326AB-B515EM2L
CIMR-G7B4015 400V 15KW(替代CIMR-HB4A0039FAA 400V 1
3150-MCM
H-PCP-J-141-D
MDLU2021N00
6AU1435-0AA00-0AA1
6ED1 052-1FB00-0BA6
6ED1055-1FB00-0BA1
140 ACI 030 00
140 CPU 434 12A
140 CPU 434 12U
140 CRA 931 00
140 CRP 931 00
140 DAI 753 00
140 DDI 841 00
140 DDO 353 00
140 DDO 843 00
140 EHC 105 00
140XTS00200
170AAI03000
170ADI35000
170ADI74050
170ADM35010
170ADO74050
170XTS00100
ABE7-CPA01
ABE7CPA02
ABE7-CPA03
TSX AEY 1600
TSX AEY 800
TSX ASY 410
TSX CPP 110
TSX DEY 16D3
TSX DSY 16T3
TSX P57 1634M
TSX P57 2634M
TSX PSY 2600M
TSX PSY 5500M
TSX SCY 21601
TSXSCP114
UM72-R-230UC/21/SO46
170PNT11020
990NAD21110
990NAD23000
990XCP98000
MA-0185-100
MAGELIS HMIGTO6315
MAGELIS XBTGT2130
TSXDSY16T2
6NH9720-3AA00
6NH9860-1AA00
6NH9910-0AA10-0AA3
KSD1-08
KSD1-16
6EP1334-2AA01
DGM60-ASAK
IC697BEM731
531X111PSHAWG3
VLT3002
6GK1561-1AA01
6ES7 331-7KF02-0AB0
6ES7 332-5HD01-0AB0
6ES7 307-1AB01-0AA0
6ES7 315-2AH14-0AB0
6ES7 321-1BLOO-0AA0
6ES7 360-3AA01-0AA0
6GK7 342-5DA02-0XE0
6EP1436-3BA00
MDV60A0450-503-4-00
KTC-PRL133/1024
416NHM30030A
IN12-THK2750
OUT19-THK-2754
UP1185
1.27.P 5UF/+-5
C274AA24600AA0J
PM864AK01 3BSE018161R1
1746-N04I
1746-NR4
3TK2907-0BB4
6ES5 980-OAE11
BSM50GD120DN2-B10
V-103-1C24-T
IC3645LXCD1TX
M155R-14ICDQ
1756-A17
1756-ENBT
1756-IF16
1756-IM16I
1756-IR61
1756-L62
1756-N2
1756-OF8