我们回顾一下,前面的目标,如下: 1、可通过宏的方式,打开或关闭检测,当关闭时检测代码全部在编译时被拿掉。 2、检测的打开,尽可能的少的影响代码本身的运行效率。检测代码的是否工作和编译效率选项无关。 3、可以进行以下几种检测。 a、是否所有malloc都free了,且malloc和free的地址是一样的。 b、是否一个指针超出了指定的寻址范围。例如一个指针希望是对刚申请的从 0x10到0x70的空间的内容进行操作。而他却正在读取或写出到0x80这个空间内。 c、可以根据条件的检测,当条件未达到前,不做检测。 d、可在执行态时,根据判断,程序暂停执行,打印一定的信息到屏幕上。
关于目标1,则目前已经的设计内容,就符合了目标。当屏蔽掉__MMDB_FLAG__后,则,c_malloc,c_free,自动修正 为,malloc ,free标准库函数。不过此时实际有个问题,malloc_free_init 和malloc_free_destory两个函数仍然存在。由此我们需要对C代码进行修改。在 malloc_free.c文件出现#include "malloc_free.h" 之后,立刻加上,#ifdef __MMDB_FLAG__ ,对应的#endif 需要一直放到文件尾端。这样才能真正的满足目标1的需求。
不错此时出现问题。test_malloc_free_main.c内在连接时,会出现,无法找到 malloc_free_init,malloc_free_destory的问题。这很正常,我们本身的目标就希望在关闭下不需要这些冗余代码。由此我 们需要修改malloc_free.h的头文件,做到,任何 #ifdef __MMDB_FLAG__成立时,出现的函数定义,和定义本身都要在另一个条件下有对应操作,由此需要调整一下头文件如下
2
//c_malloc c_free means malloc by check,not calloc,not type cmalloc!!!!!
3
#define c_malloc(a) malloc(a)
4
#define c_free(a) free(a)
5
#define MALLOC_FREE_INIT(...) do {} while (0)
7
#define MALLOC_FREE_INIT malloc_free_init
这里的...是利用了C标准里,可变参的知识。表示任意参数。但无论什么参数。我们都将其对等于一个空内容。在#define 扩展后,调用malloc_free_init(0);的地方会对等替换成 “空;” 此时,编译可以认为是个无效的空语句。
不过对于诸如
就无法使用上述方法。此时会扩展为 a = ; 几乎没有好的解决方案回避这个问题。因此,在设计需要能通过宏进行可屏蔽的代码时,尽可能不使用带返回的函数描述方式。上述做法更好的描述应该是
1
#define FUNC_(a,b,c,d) do {a = func(b,c,d);}while(0)
用全大写,是方便区分,函数调用还是宏调用。
这也是为什么在条件成立时,出现一个对malloc_free_init名称替换的目的。当然严格说,c_malloc c_free也需要进行全大写替换,此处暂时不形而上学。记得对应修改test_malloc_free_main中调用 malloc_free_init的书写方式,修改为全大写。
关于目标2,这个是个比较抽象的目标。判断标准应该是增加的代码,尽可能小巧和简单。减少代码的复杂度。同时将比较复杂的操作,通过函数的调用方式实现这 样降低了被检测的代码片额外的代码量,而我们尽可能少的调用这些函数,这样降低了被检测代码片额外的执行量,只有在条件成立下。
关于目标3,现在我们只补充a,b,c的。d,原先想用个弱智方式实现,但觉得利用这个介绍一下多线程设计很不错,所以我们放后面讨论。
关于a,前面已经做的OK了。但是关于b,c我们还没有实现。下面先针对b进行实现。
目标b,是要判断一个指针是否在一个malloc过的空间内,防止指针被改写或不正确设置值时,指向其他地址空间。由此必须要有个判断值,通过对曾经malloc的信息进行对比。为了实现这个目的,必须增加数据。如下
1
typedef
struct
{
//not add other type ,only void *
5
static
_BUF_RANGE *ptab = 0;
需要都放在C文件里,因为其他C文件不关心的东西,我们没必要折腾到头文件嘛。为什么不用如下形式
这是为了简化比较逻辑。当在代码里,需要对指针进行检测,那么用第一个方案可以如下写
1
(ptab->pfirst >= p) && (ptab->plast < p)
第二个方案,得如下写
1
(ptab->pfirst >= p) && ((ptab->pfirst + ptab->size) < p)
无缘无故的多了一步加法,而这个加法在size确定下,有时任意时刻一致的结果。何必呢?
而对于ptab,显然需要有个足够的空间,空间大小怎么来,由MAX_MALLOC_NUM 确定,在 malloc_free_init里,进行申请,如果失败则认为致命错误,直接退出。同时在malloc_free_destory进行释放。
此时我们需要修改一下c_malloc,和c_free。一个是增加信息,一个是检测信息。
c_malloc在成功申请后,需要对ptab里的内容进行设置。如下 set_malloc_tab函数
此处多了个宏定义,
1
#define DO_ERR_EX_NO_SET(E) do {int tmp;DO_ERR_EX(tmp,ERR_TAB_FLAG) ;}while (0)
这里tmp没有意义,是为了利用DO_ERR_EX的宏,尽量合并过程,是C模块化过程化编写的原则,而此时malloc_count 由于可能还有其他的检测,因此我们暂时不能清除,因为当前的问题不是由malloc_count本身导致的,这和前面使用 DO_ERR_EX(malloc_count)的情况不一样。
01
static
void
set_malloc_tab(
void
*p,
size_t
size){
02
int
bias = malloc_count;
04
while
(ptab[bias].pfirst && bias < MAX_MALLOC_NUM){
07
if
(bias >= MAX_MALLOC_NUM){
09
while
(ptab[bias].pfirst && bias < malloc_count){
13
if
(ptab[bias].pfirst){
14
DO_ERR_EX_NO_SET(ERR_TAB_FLAG);
16
ptab[bias].pfirst = p;
17
ptab[bias].plast = p + size;
这里存在一个简单的全扫描检测空存储空间的工作。由于malloc的发生我们本身并不希望他频繁,所以对set_malloc_tab没有效率要求,因此简化了寻找空地址的工作,这个和普通的memory管理不一样。设计程序,
有个很重要的原则,把有限的精力放在目标问题上,
绝大多数的代码都不是最优的描述,因为最优本身就是可变化的。
if (bias >= MAX_MALLOC_NUM) 是因为,我们假设当前malloc_count之后的空间可能空的空间更多,因此直接从bias = malloc_count开始扫描,但这并不代表当malloc_count < MAX_MALLOC_NUM时,就一定在这个区间段有可利用的资源。可能前面已申请的空间被释放了。由此需要进行从头的补扫描,如果第一个while没 有发现有效空间时。
上述两个while,无论哪个,必须表示ptab[bias].pfirst == 0,才是有效,因此,判断是否有足够的空间时,既然已经全扫描了,我们就可以通过它来判断,而不是简单的 malloc_count < MAX_MALLOC_NUM来判断。
代码设计时,需要注意,
在不增加额外代码时,最好使用直接关联的逻辑来处理
,对等逻辑例如 malloc_count < MAX_MALLOC_NUM确实和ptab[bias].pfirst 是否为0 ,存在对应关系,但是这只是理论上的。如果malloc_count本身就错了呢?例如其他的地方没有free却修改了malloc_count。这里的 DO_ERR_EX_NO_SET本身也是对malloc_count的正确性判断的错误输出。
上述这个观点,是非常重要,也是初学者非常容易忽视的。觉得,一个表达,这样也可以做,那样也可以做。想想一个目标可以多种方式实现是好事情,但目的是搞 清楚为什么,在搞清楚之后,能够简化逻辑与逻辑之间的关联。尽量直接的表达逻辑。否则此处就是个潜在的BUG难点。当malloc_count本身被外部 修改出错,但修改的地方并不会出现系统出错问题。反倒是这里会出现系统崩溃,这样的错误转移,导致debug难度加大。
其原因就是在代码设计时,用逻辑映射逻辑的方式,将错误给转移了过来。
小工程无所谓,大工程,等着吃苦吧。
有设置,一定要想到有清除,且不谈有查找。如同有init,就有destory,哪怕你什么都没做,如同我的create_module创建的C的模板一样,但是你得保留代码片,省得以后忘记。以下就是清除部分的代码
01
static
int
check_clear_malloc_table(
void
*p){
03
int
bias = malloc_count;
04
while
((i < bias) && (ptab[i].pfirst!=p)){
05
bias += (ptab[i++].pfirst == 0);
为什么多增加了一个check,是因为set是假设可以set的,实际是否有空间是外部通过 malloc_count < MAX_MALLOC_NUM来判断。而 clear之所以要和check进行整合,是因为 clear的前提条件不单单是是否存在没有free对指针,还要判断指针是否合法。而这个工作,集中处理,要比分开处理更有效的防止匹配错误。例如,没有 check就clear,或没有clear,以为check就clear了。
因为clear很难有什么先验的信息,此处和set不同。因此while 是从0开始的。从malloc_count开始就画蛇添足了。当然可以修改为,从malloc_count 开始向0进行反向扫描。不过机器的cache 机制告诉我们,
循环,尽可能后向检测,不要前向检测
。
这里说了set,立刻说clear,并废话一堆,这个clear下的动作,在set里是对应的什么。是希望新手注意,面向模块,的设计,
对于大多数的数据区如果存在有意义的设置动作,必然会存在对等的清理动作。哪怕他没有必要,但也要有这个概念
。特别是你在练习消息,通讯等交互工作设计时。
既然能SET了,也能CLEAR了。那么我们就应该可以做查找判断了。一种简单的做法,是我们每次针对一个指针,对整个malloc记录信息表进行查找。不过这显得很无聊。因为我们对任何一个代码片的指针,从设计的角度都知道这个指针应该指向什么。我们
不是在追问,这个指针目前指向哪个区域,而是这个指针针对某个malloc申请的空间,是否越界了
。如果是前者,对于后者的问题毫无帮助。如果一个指针从A的区,指向了B的区,一样还是错啊。因此上述简单的做法,就是个错误的方式,先不谈效率。效率永远是最后的话题,而且还得当你发现他慢到,成为一个问题的时候才是问题。
因此正确的做法是,需要一个带比较的基准区域,也就是我们得知道是malloc信息表中的那个数据。由此我们需要获取一个索引,用于判断。如下,
01
void
** get_malloc_index(
void
*ptr){
04
for
(i = 0,bias = 0 ; bias < malloc_count && i < MAX_MALLOC_NUM; i++){
05
if
(ptab[i].pfirst == ptr)
return
&(ptab[i].pfirst);
06
bias += (ptab[i].pfirst !=0);
08
DO_ERR_EX_NO_SET(ERR_PTR_NOFOUND);
这里, 从0开始的目的和前面clear的情况一样。由此该函数也被定义为,不可频繁执行的函数。需要在类似malloc的地方紧随使用。为什么用void**, 不用_BUF_RANGE *,是因为我们要简化头文件,头文件越简单,则对于__MMDB_FLAG__开启关闭的差异性越小,由此越能保证代码设计时的正确性。内容少,出错的概 率就小嘛。只是习惯问题,你完全可以修改,将 _BUF_RANGE 放到头文件里,使用
_BUF_RANGE *get_malloc_index(void*ptr){ 方式获取对应信息。
使用void **,则可以
假设pvv = get_malloc_index(ptr);
简单利用 pvv[0] pvv[1]对等 (ptab+i)->pfirst ,(ptab+i)->plast。这也是为什么我坚持在_BUF_RANGE里都定义为void *的原因。
获取get_malloc_index还不够。因为他传递给了一个变量,而这个变量总要申明吧。由此,我们在头文件里需要添加如下信息。
1
#define _TYPE_INDEX_MALLOC_FREE(name) void ** name;
记得,如果你尝试在一个函数内使用, _TYPE_INDEX_MALLOC_FREE(pbufinfo);
则会导致作用域的问题在别的函数内无效。最好在这个C文件的最上方定义。同时这样的定义我没有强制为 static,是因为有很多情况,malloc一个空间,而利用该空间的指针往往不在一个模块里。所以使用了全局变量,但由此可能会导致重名问题。因此, 最好对name 的命名能准确描述该空间的含义。那么就存在一个配置的工作,如下
假设是上面的pbase则
1
_TYPE_INDEX_MALLOC_FREE(pbufinfo);
//此处申明一个索引变量
2
void
*pbuf = c_malloc(SIZE);
//申请一个SIZE大小的空间给pbuf
3
pbufinfo = get_malloc_index(pbuf);
//将pbuf的空间信息的地址传递给pbufinfo
当然,你可以提出,此处有个简化方式,将pbufinfo当作参数给予 c_malloc,如果我不关系某个c_malloc的信息,可以传递个0.这样确实可以做。但直接影响到当__MMDB_FLAG__关闭时, #define c_malloc malloc的宏的修正。这里就又提出一个编程思想。
当你的一个代码片的增加,如果引入到其他代码片时,会出现其他代码片全范围的修改,则最好慎用。
例 如上面将get_malloc_index的动作作为c_malloc的动作,如果只是在c_malloc内部实现,并不影响参数,由此不会影响 __MMDB_FLAG__关闭时的逻辑,则完全可以。反之则不要合并。这样的合并会导致和目标无关的逻辑关联。简化逻辑关联,是分解问题,分析问题,归 总设计方案的一个原则。何必额外增加复杂度呢?
参考前面关于malloc_free_init的讨论,我们需要对get_malloc_index包装一下,用宏的全大写方式展开,这样有利于__MMDB_FLAG__关闭时的剥离,所以头文件修改如下,以下增加了对指针的判断检测
03
#define _TYPE_INDEX_MALLOC_FREE(...)
04
#define GET_MALLOC_INDEX(...) do{}while (0)
05
#define CHECK_PTR_RANGE(...) (1)
09
#define _TYPE_INDEX_MALLOC_FREE(name) void ** name;
10
#define GET_MALLOC_INDEX(p,indexP) do{indexP = get_malloc_index(p);}while (0)
11
#define CHECK_PTR_RANGE(p,indexP) ((indexP[0] <= (void *)(p)) && (indexP[1] > (void*)(p)))
这里需要说明,CHECK_PTR_RANGE,既然是判断用途,因此,需要用()进行包裹,而为什么在__MMDB_FLAG__关闭是变成了(1), 是因为,我们默认这个判断更多情况下是条件成立,所以在关闭是,为了保证代码不做改动,则我们也默认为(1),放心,编译器当发现 if (1) {...} else {...}时,会把if (1)以及else后面的语句全部拿掉。永远判断均位1,何必判断,永远跑不进的代码何必保留呢?但这个是针对编译器而言,对于你,运行态和检测态是都有 可能发生的。
但通常错了,总要有对应动作。而这个动作,需要包裹在宏里面,否则,在 __MMDB_FLAG__关闭下,需要ctrl+ X掉。因此,我们再增加一个宏
1
#define CHECK_PTR_RANGE_ER(p,indexP,n,NAME) do {\
2
if
(CHECK_PTR_RANGE(p,indexP)){n++;}
else
{\
3
set_check_ptr_range_error_exit(p,indexP,n,NAME);}}
while
(0)
这里说下n,n是用于计数的,目的是,检测第几次发生,由此可以通过检测这个值,在个值发生前,可以做点信息打印之类的事情,检测逻辑正确性,甚至另代码停滞,以观测判断一些变量是否被修改,而导致指针出错。因此多出这个变量,计数值。也需要宏包裹一下,如下
1
#define _TYPE_COUNT_MALLOC_FREE(name) unsigned long name = 0;
以下,就给出.h和.c的全部清单。记得关注一下 ERR_MAX_NUM在枚举中的作用,虽然这个并不是你需要的枚举类型。
01
#ifndef _malloc_free_H_
02
#define _malloc_free_H_
04
#define ALLOC_PAGE_SIZE 4096 //mininum malloc unit sizes ,not change
05
#define MALLOC_NUM_UNIT_SIZE (ALLOC_PAGE_SIZE / sizeof(void*))
06
#define MAX_MALLOC_UNIT_NUM 64 //not more than 4096*8
07
#define MAX_MALLOC_NUM (MALLOC_NUM_UNIT_SIZE * MAX_MALLOC_UNIT_NUM) // max malloc times ,you can change
08
//#define __MMDB_FLAG__
10
//c_malloc c_free means malloc by check,not calloc,not type cmalloc!!!!!
11
#define c_malloc(a) malloc(a)
12
#define c_free(a) free(a)
13
#define MALLOC_FREE_INIT(...) do{}while(0)
14
#define _TYPE_INDEX_MALLOC_FREE(...)
15
#define _TYPE_COUNT_MALLOC_FREE(...)
16
#define CHECK_PTR_RANGE(...) (1)
17
#define GET_MALLOC_INDEX(...) do{}while (0)
18
#define CHECK_PTR_RANGE_ER(...) do{}while(0)
21
#define MALLOC_FREE_INIT malloc_free_init
22
#define _TYPE_COUNT_MALLOC_FREE(name) unsigned long name = 0;
23
#define _TYPE_INDEX_MALLOC_FREE(name) void ** name;
24
#define CHECK_PTR_RANGE(p,indexP) ((indexP[0] <= (void *)(p)) && (indexP[1] > (void*)(p)))
25
#define GET_MALLOC_INDEX(p,indexP) do{indexP = get_malloc_index(p);}while (0)
26
#define CHECK_PTR_RANGE_ER(p,indexP,n,NAME) do {if (CHECK_PTR_RANGE(p,indexP)){n++;}else{set_check_ptr_range_error_exit(p,indexP,n,NAME);}} while (0)
35
void
memory_free_init(
void
*);
36
void
**get_malloc_index(
void
*ptr);
//not used in code ,please used GET_MALLOC_INDEX define
37
void
set_check_ptr_range_error_exit(
void
*p,
void
**index,unsigned
long
n,
const
char
*str);
//not used in code ,please used CHECK_PTR_RANGE_ER
38
void
*c_malloc(
size_t
size);
39
void
c_free(
void
*ptr);
44
#endif //_malloc_free_H_
005
#include "malloc_free.h"
008
typedef
struct
{
//not add other type ,only void *
012
#define BUF_RANGE_SIZE (sizeof(_BUF_RANGE)/sizeof(void *))
026
const
static
char
error_str[ERR_MAX_NUM][256] = {
"malloc_free is ok!\n"
,
"too much free func called!\n"
,\
028
"too much alloc func called!\n"
,
029
"malloc called failed!\n"
,
030
"malloc_count or tab flag error!\n"
,
031
"try to free zero address error!\n"
,
032
"no found the address is malloc error!\n"
,
033
"want to get one ptr index ,but the ptr not malloc !\n"
,
034
"ptr range check error !\n"
};
035
#define ERROR(n) do {error_type = ((n)<ERR_MAX_NUM?n:error_type);}while(0)
036
#define DO_ERR_EX(n,E) do {ERROR(E);n = 0;exit(1);} while (0)
037
#define DO_ERR_EX_NO_SET(E) do {int tmp;DO_ERR_EX(tmp,ERR_TAB_FLAG) ;}while (0)
038
#define CHECK_ALLOC(n) do {if ((n)>=MAX_MALLOC_NUM){DO_ERR_EX(n,ERR_ALLOC_OVERFLOW);}}while(0)
039
#define CHECK_FREE(n) do {if ((n) == 0){DO_ERR_EX(n,ERR_FREE_MORE);}}while(0)
040
#define CHECK_FREE_LACK(n) do {if ((n)){ERROR(ERR_FREE_LACK);}}while(0)
041
#define CHECK_MALLOC(p) do {if (p == 0){DO_ERR_EX(malloc_count,ERR_MALLOC);}}while(0)
042
#define SET_ZERO(p,T,s) do {T *tp = (T)(p); int i; for (i = 0 ; i < s ;i++){*tp++ = 0;} }while (0)
043
static
int
malloc_free_flag =0;
044
static
long
malloc_count = 0;
045
static
unsigned
int
error_type = 0;
046
static
_BUF_RANGE *ptab = 0;
048
void
malloc_free_destory(
void
);
049
void
malloc_free_init(
void
*pv){
050
if
(malloc_free_flag) {
051
//log("module inited..",X);
054
malloc_free_flag = 1;
055
//todo:module init...
057
ptab = (_BUF_RANGE*)
malloc
(
sizeof
(_BUF_RANGE)*MAX_MALLOC_NUM);
058
SET_ZERO(ptab,
void
*,MAX_MALLOC_NUM*BUF_RANGE_SIZE);
060
SET_ZERO(tflag,_tBIT_FLAG,BIT_FLAG_SIZE);
062
atexit
(malloc_free_destory);
065
static
void
set_malloc_tab(
void
*p,
size_t
size){
066
int
bias = malloc_count;
068
while
(ptab[bias].pfirst && bias < MAX_MALLOC_NUM){
071
if
(bias >= MAX_MALLOC_NUM){
073
while
(ptab[bias].pfirst && bias < malloc_count){
077
if
(ptab[bias].pfirst){
078
DO_ERR_EX_NO_SET(ERR_TAB_FLAG);
080
ptab[bias].pfirst = p;
081
ptab[bias].plast = p + size;
085
static
int
check_clear_malloc_table(
void
*p){
087
int
bias = malloc_count;
088
while
((i < bias) && (ptab[i].pfirst!=p)){
089
bias += (ptab[i++].pfirst == 0);
100
void
*c_malloc(
size_t
size){
102
CHECK_ALLOC(malloc_count);
105
set_malloc_tab(re,size);
109
void
c_free(
void
*ptr){
111
if
(check_clear_malloc_table(ptr)){
112
CHECK_FREE(malloc_count);
118
DO_ERR_EX_NO_SET(ERR_FREE_NOFOUND);
121
DO_ERR_EX_NO_SET(ERR_FREE_ZERO);
125
void
malloc_free_destory(
void
){
126
if
(!malloc_free_flag) {
127
//log("module not inited..",X);
130
malloc_free_flag = 0;
131
//todo:module destory...
132
if
(error_type == 0){
133
CHECK_FREE_LACK(malloc_count);
135
if
(ptab)
free
(ptab);
136
fprintf
(stderr,
"%s"
,error_str[error_type]);
139
void
set_check_ptr_range_error_exit(
void
*p,
void
**indexP,unsigned
long
n,
const
char
*strname){
143
fprintf
(stderr,
"ptr:%s\n"
,strname);
145
fprintf
(stderr,
"in %ld times, found 0x%llx not in buf\n buf is [0x%llx,0x%llx]\n"
,n,(unsigned
long
long
)p,(unsigned
long
long
)indexP[0],(unsigned
long
long
)indexP[1]);
146
DO_ERR_EX(tmp, ERR_RANGE_NOFOUND);
149
void
** get_malloc_index(
void
*ptr){
152
for
(i = 0,bias = 0 ; bias < malloc_count && i < MAX_MALLOC_NUM; i++){
153
if
(ptab[i].pfirst == ptr)
return
&(ptab[i].pfirst);
154
bias += (ptab[i].pfirst !=0);
156
DO_ERR_EX_NO_SET(ERR_PTR_NOFOUND);
这里谈一下,test_malloc_free_main.c的作用。之所以我在设计create_module脚本时默认自动生成一个 test_MODULENAME_main.c的文件,是用于持久保留模块设计中,对于功能的检测。越重视这些东西,对你后期的大系统设计越有帮助。
test7函数里,给出了两种检测方法,一种检测,是不调用 malloc_free的内部函数而自行添加代码。但是这种方案不好。违背了 __MMDB_FLAG__的原则。当__MMDB_FLAG__被关闭是,printf("p2 bias is %d , check ok\n",i);会持久保留。只是给出建议,当使用ptr时,你可以如这种方案操作。而对于错误点检测,通常是需要当作严重错误来停滞的。除非你尝试工 作运行态下的检测,总得有对应操作吧,另谈。其源码如下。
001
#include "malloc_free.h"
004
typedef
void
(* TEST_FUNC)(
void
);
006
static
void
test0(
void
){
010
p1 =(
char
*)c_malloc(4);
//*4);
011
p2 = (
char
*)c_malloc(6);
014
return
;
//normal check
016
static
void
test1(
void
){
018
p1 = (
char
*)c_malloc(5);
019
p2 = (
char
*)c_malloc(6);
022
return
;
//free lack check
024
static
void
test2(
void
){
026
p1 = (
char
*)c_malloc(5);
027
p3 = p2 = (
char
*)c_malloc(6);
031
return
;
//free more check
033
static
void
test3(
void
){
034
char
**pp = (
char
**)c_malloc(
sizeof
(
char
*)*MAX_MALLOC_NUM + 1);
036
for
(i = 0 ; i <= MAX_MALLOC_NUM ; i++){
037
pp[i] = (
char
*)c_malloc(2);
039
return
;
//alloc more check
041
static
void
test4(
void
){
043
p1 = (
char
*)c_malloc(5);
044
p2 = (
char
*)c_malloc(6);
045
p3 = (
char
*)c_malloc(6);
049
return
;
//free twin check
051
static
void
test5(
void
){
053
p1 = (
char
*)c_malloc(5);
054
p2 = (
char
*)c_malloc(6);
057
return
;
//free shift check
059
static
void
test6(
void
){
061
p1 = (
char
*)c_malloc(5);
062
p2 = (
char
*)c_malloc(6);
065
return
;
//free zero check
068
static
void
test7(
void
){
070
_TYPE_COUNT_MALLOC_FREE(ptr_count);
071
_TYPE_INDEX_MALLOC_FREE(pindex);
074
p1 = (
char
*)c_malloc(5);
075
GET_MALLOC_INDEX(p1,pindex);
077
for
(i = 3 ; i< 10 ; i++,p2++){
078
if
(CHECK_PTR_RANGE(p2,pindex)){
079
printf
(
"p2 bias is %d , check ok\n"
,i);
081
printf
(
"error bias is %d!\n"
,i);
085
for
(i = 0 ; i< 10 ; i++,p2++){
086
CHECK_PTR_RANGE_ER(p2,pindex,ptr_count,
"test7 func p2"
);
091
return
;
//free zero check
094
TEST_FUNC test_a[TEST_MASK+1]= {test0,test1,test2,test3,test4,test5,test6,test7};
097
int
main(
int
argc,
char
*argv[]){
100
printf
(
"hello test_malloc_free_main now run...\n"
);
103
printf
(
"need parameters!\n"
);
106
mode = argv[1][0] -
'0'
;
107
test_a[mode & TEST_MASK]();
109
printf
(
"hello test_malloc_free_main now exit...\n"
);
转自:http://my.oschina.net/luckystar/blog/67098