一直以来都比较关注内存管理问题,诸如碎片,泄漏,非法引用等问题成为C语言程序中的安全隐患。稍微留心一点就可以发现通常每个产品级的C程序都有专门的
内存管理接口来封装底层的内存机制,使得上层不必再纠缠于内存管理的细节。内存管理器从最初到现在写了不下20个版本,每次发现或想到新算法,都要重写一
遍,以优化性能。以下是我最近写的一款内存管理器,基于内存池,虽然池算法很普遍,不过对内存管理来说,重在细节。
为测试该接口,专门写了自动测试脚本进行“饱和轰炸”,程序稳定运行,并未出现异常,并且根据统计显示,内存利用率很高,因为基于内存复用,因此池的个数基本稳定在3块。
/* memmgr2.h */
#ifndef _memmgr_2_h
#define _memmgr_2_h
#define NEWN(n,size) memory_new((n)*(size),__FILE__,__FUNCTION__,__LINE__)
#define NEW(size) NEWN(1,size)
#define NEWNP(n,ptr) NEWN( ( n ) , sizeof *( ptr ) )
#define NEWP(ptr) NEWNP(1, ( ptr ) )
#define RESIZE(ptr,size) memory_resize(ptr,size,__FILE__,__FUNCTION__,__LINE__)
#define FREE(ptr) memory_free(ptr,__FILE__,__FUNCTION__,__LINE__)
#define Check_Memory_Status(ptr) memory_status_string(ptr)
#define Check_Memory_Leaking() memory_leaking_check();
extern void * memory_new ( int size ,
const char *file , const char *func , const int line);
extern int memory_free( void * ptr ,
const char *file , const char *func , const int line);
extern void *memory_resize(void *ptr , int size_data ,
const char *file , const char *func , const int line);
extern const char * memory_status_string(void *ptr);
extern void memory_leaking_check(void);
#endif
/* memmgr2.c */
#define DEBUG1
//#define DISABLE_MSG
//#define DISABLE_SHOW
#define DISABLE_D
#if 0
在设计的过程中常忘记写返回值,导致常常出问题
还有一种是return_val_if_fail,这种是有异常的时候才返回
所以,需要在后面添上正常情况的返回值,这里很容易漏掉
#endif
#include "c.h"
#include "memmgr2.h"
#include "memleak.h"
#define Memory_Size_512K (1<<19)
#define Memory_Size_1M (1<<20)
#define Memory_Size_4M (1<<22)
#define Global_Pool_Size Memory_Size_1M
#define Min_Data_Size 4
#define Max_Chain_Array_Length 15
#define Max_Large_Size Memory_Size_4M
#define Max_Chain_Block_Size Memory_Size_512K
#define Min_Chain_Block_Size 32
#define Pointer_In_Zone(ptr,left,right) /
((char*)(ptr)-(char*)(left)>=0 && (char*)(ptr)-(char*)(right)<=0)
struct descriptor {
const char *file;
const char *func;
int line;
int size;
struct descriptor *next;
};
struct memory_pool {
char *end;
char *last;
int failed;
struct memory_pool *current;
struct memory_pool *next;
};
struct memory_chain {
struct descriptor *deactive;
struct descriptor *active;
int block_size;
};
static struct memory_manager {
struct memory_pool *pool;
struct descriptor *large;
int max_block_size;
int large_count;
int pool_count;
int allocate_from_large_stamp;
int allocate_from_pool_stamp;
int allocate_from_chain_stamp;
long long allocate_memory_stamp;//pool+large
long long allocate_data_stamp;//memory_new size sum
double ratio;
struct memory_chain chain[Max_Chain_Array_Length];
}g_mmgr;
//暂时不考虑内存对齐的问题
union align {
int i;
long l;
long *lp;
void *p;
void (*fp)(void);
float f;
double d;
long double ld;
};
static struct memory_pool *alloc_memory_pool(void);
///
///
static inline void inc_alloc_memory_stamp(int size)
{
return_if_fail(size>=Min_Data_Size);
g_mmgr.allocate_memory_stamp += size;
if(g_mmgr.allocate_memory_stamp)
g_mmgr.ratio=1.0*g_mmgr.allocate_data_stamp/g_mmgr.allocate_memory_stamp;
}
static inline void inc_alloc_data_stamp(int size)
{
return_if_fail(size>=Min_Data_Size);
g_mmgr.allocate_data_stamp += size;
if(g_mmgr.allocate_memory_stamp)
g_mmgr.ratio=1.0*g_mmgr.allocate_data_stamp/g_mmgr.allocate_memory_stamp;
}
#define Union_Align_Size (sizeof(union align))
#define Align_Size(size) (Round_Up((size),Union_Align_Size))
#define Desptr_Size (sizeof(struct descriptor))
#define PDesptr_Size (sizeof(struct descriptor*))
#define Data_Package_Size(size) (Align_Size(size)+Desptr_Size)
#define Desptr_Package_Size(desptr) (Data_Package_Size(desptr->size))
#define Min_Package_Size (Data_Package_Size(Min_Data_Size))
#define Data_Addr_of_Pool(pool) (char*)((char*)pool+sizeof *(pool))
#define Pool_End(pool) (char*)((char*)(pool)+Global_Pool_Size)
//保证是对齐后的
void *sys_new(int size)
{
return_val_if_fail(size >= Min_Data_Size,0);
void *ptr=calloc(1,size);
return_val_if_fail(ptr!=0 , 0);
inc_alloc_memory_stamp(size);
return ptr;
}
void sys_free(void *ptr)
{
return_if_fail(ptr!=0);
if(ptr != 0)free(ptr);
}
static int init_memory_manager(void)
{
Zero_Memory(&g_mmgr);
struct memory_pool *pool=alloc_memory_pool();
return_val_if_fail(pool!=0 , -1);
int i;
int chain_block_size=Min_Chain_Block_Size;
struct memory_chain *chain=g_mmgr.chain;
for(i=0 ; i
chain[i].block_size=chain_block_size;
chain_block_size <<= 1;
}
return_val_if_fail(
chain[i-1].block_size <= Max_Chain_Block_Size , -1
);
g_mmgr.max_block_size=chain[i-1].block_size;
return 0;
}
//size has been aligned
#define Enough_Space_for_Alloc(pool,size) /
( (char*)((pool)->last + (size)) <= Pool_End(pool))
#define Set_Desptr(desptr,_file,_func,_line,_size) do { /
desptr->file=_file;/
desptr->func=_func;/
desptr->line=_line;/
desptr->size=_size;/
} while(0)
#define Ptr_Entry_Desptr(ptr) ((struct descriptor*)((char*)(ptr)-Desptr_Size))
#define Desptr_Entry_Ptr(desptr) ((char*)((char*)(desptr)+sizeof *(desptr)))
#define Show_Desptr(message,desptr) do { /
err_msg("/n%s/n",message);/
Show_Value(desptr->file,s);/
Show_Value(desptr->func,s);/
Show_Value(desptr->line,d);/
Show_Value(desptr->size,d);/
}while(0)
///
///
typedef int (*compare_func)(void *data,void *val);
typedef void **(*entry_next_func)(void *data);
int default_compare(void *data,void *val)
{
return (int)((char*)data-(char*)val);
}
static void ** search_slist(
void **head,
int (*compare)(void *data,void *val),
void **(*entry_next)(void *data),
void *val
)
{
void **pp = 0;
for(pp = head; pp && *pp; pp = entry_next(*pp))
if(compare(*pp,val) == 0) break;
return pp;
}
static inline struct memory_pool **entry_next_pool(struct memory_pool *pool)
{
return pool ? &pool->next : 0;
}
static inline struct descriptor **entry_next_desptr(struct descriptor *desptr)
{
return desptr ? &desptr->next : 0;
}
static int compare_pool_for_enough_space(
struct memory_pool *pool , int size_package)
{
if(Enough_Space_for_Alloc(pool,size_package)) return 0;
if(pool->failed++>4) pool->current = pool->next;
return -1;
}
static struct memory_pool *search_pool_for_enough_space(int size_package)
{
return_val_if_fail(
size_package >= Min_Package_Size
&& size_package <= g_mmgr.max_block_size,
0,
"Allocate Size Not In Normal Range , "
"%d out of [ %d , %d ]",
size_package , Min_Package_Size ,
g_mmgr.max_block_size
);
void **pp = search_slist(
(void ** )&g_mmgr.pool->current,
(compare_func )compare_pool_for_enough_space,
(entry_next_func )entry_next_pool,
(void * )size_package
) ;
return *(struct memory_pool **)pp ;
}
static int compare_pool_for_desptr(struct memory_pool *pool,
struct descriptor *desptr)
{
void *left = Data_Addr_of_Pool(pool);
void *right = pool->last-Min_Package_Size;
if(Pointer_In_Zone(desptr,left, right)) return 0;
return -1;
}
static struct memory_pool *search_pool_for_desptr(struct descriptor *desptr)
{
return_val_if_fail(desptr != 0 , 0);
void **pp = search_slist(
(void ** )&g_mmgr.pool,
(compare_func )compare_pool_for_desptr,
(entry_next_func )entry_next_desptr,
(void * )desptr
);
return *(struct memory_pool **)pp;
}
static struct descriptor **search_large_for_desptr(struct descriptor *desptr)
{
return_val_if_fail(desptr != 0, 0);
void **pp = search_slist(
(void ** )&g_mmgr.large,
(compare_func )default_compare,
(entry_next_func )entry_next_desptr,
(void * )desptr
);
return (struct descriptor**)pp;
}
static struct memory_chain *search_chain_for_data_size(int size_data)
{
int size_package=Data_Package_Size(size_data);
return_val_if_fail(
size_package >= Min_Package_Size
&& size_package <= g_mmgr.max_block_size,
0,
"There is no Chain for Such Data Package Size"
" , %d out of [ %d , %d ]",
size_package , Min_Package_Size , g_mmgr.max_block_size
);
struct memory_chain *chain=g_mmgr.chain;
int i;
for(i=0 ; i < Max_Chain_Array_Length ; i++){
if(chain[i].block_size >= size_package)
return &chain[i];
}
return 0;
}
static struct memory_chain *search_chain_for_desptr(struct descriptor *desptr)
{
return desptr ? search_chain_for_data_size(desptr->size) : 0;
}
static struct descriptor **search_active_for_desptr(
struct memory_chain *chain , struct descriptor *desptr)
{
return_val_if_fail(chain != 0 , 0);
return_val_if_fail(desptr != 0 , 0);
void **pp = search_slist(
(void ** ) &chain->active,
(compare_func ) default_compare,
(entry_next_func) entry_next_desptr,
(void * ) desptr
);
return (struct descriptor **)pp;
}
static struct descriptor **search_chain_active_for_desptr(struct descriptor *desptr)
{
struct memory_chain *chain=search_chain_for_desptr(desptr);
return_val_if_fail(chain != 0 , 0);
return search_active_for_desptr(chain,desptr);
}
static struct descriptor **search_chain_deactive_for_desptr(struct descriptor *desptr)
{
struct memory_chain *chain=search_chain_for_desptr(desptr);
return_val_if_fail(chain!=0 , 0);
void **pp = search_slist(
(void ** ) &chain->deactive,
(compare_func ) default_compare,
(entry_next_func) entry_next_desptr,
(void * ) desptr
);
return (struct descriptor **)pp;
}
///
///
static int desptr_add2_chain_active(struct descriptor *desptr)
{
return_val_if_fail(desptr != 0 , -1);
struct memory_chain *chain=search_chain_for_desptr(desptr);
return_val_if_fail(chain != 0 , -1);
desptr->next = chain->active;
chain->active = desptr;
return 0;
}
#define Clear_Desptr(desptr,size) Bzero(Desptr_Entry_Ptr(desptr),(size)-sizeof *(desptr))
static int desptr_add2_chain_deactive(struct descriptor *desptr,struct memory_chain *chain)
{
return_val_if_fail(desptr!=0,-1);
return_val_if_fail(chain!=0,-1);
Clear_Desptr(desptr,chain->block_size);
desptr->next=chain->deactive;
chain->deactive=desptr;
return 0;
}
static int desptr_add2_deactive(struct descriptor *desptr)
{
return_val_if_fail(desptr!=0,-1);
struct memory_chain *chain=search_chain_for_desptr(desptr);
return_val_if_fail(chain!=0,-1);
return desptr_add2_chain_deactive(desptr,chain);
}
///
///
static struct memory_pool *alloc_memory_pool(void)
{
struct memory_pool *pool=sys_new(Global_Pool_Size);
return_val_if_fail(pool!=0,0);
g_mmgr.pool_count++;
pool->last=Data_Addr_of_Pool(pool);
pool->end=Pool_End(pool);
pool->current=pool;
pool->failed=0;
pool->next=g_mmgr.pool;
g_mmgr.pool=pool;
return pool;
}
//数据大小,所以需要内部对其
static void *alloc_from_large(int size_data,
const char *file , const char *func , const int line)
{
return_val_if_fail(size_data >= Min_Data_Size,0);
int size_package = Data_Package_Size(size_data);
return_val_if_fail(
size_package > g_mmgr.max_block_size
&& size_package <= Max_Large_Size,
0,
"Allocate Data Package Size Not In The Normal Range"
" , %d Out of [ %d , %d ] .",
size_package , g_mmgr.max_block_size , Max_Large_Size
);
struct descriptor *desptr=(struct descriptor*)sys_new(size_package);
return_val_if_fail(desptr!=0,0,"Allocate Large Memory Failed");
Set_Desptr(desptr,file,func,line,size_data);
desptr->next=g_mmgr.large;
g_mmgr.large=desptr;
g_mmgr.large_count++;
g_mmgr.allocate_from_large_stamp++;
inc_alloc_data_stamp(size_data);
return Desptr_Entry_Ptr(desptr);
/*
以下函数在sys_new中就自动设置了
int_alloc_memory_stamp(size_package);
*/
}
#if 0
一个bug,在pool中申请内存时通常是因为chain deactive中没有,此时不能传入size_Data
给pool,应按size_data在chain中的block_size传,否则pool会按Data_Package_Size分,
造成分配过小,这样容易造成数据覆盖
注意分清size_data,size_package,size_block区别
#endif
//数据大小,内部对齐
static void *alloc_from_pool(int size_data ,
const char *file , const char *func , int line)
{
int size_package = Data_Package_Size(size_data);
struct memory_chain *chain=search_chain_for_data_size(size_data);
int size_block = chain->block_size;
return_val_if_fail(chain!=0,0,"Chain For Data Size Null");
return_val_if_fail(
size_package >= Min_Package_Size
&& size_package <= g_mmgr.max_block_size,
0,
"Allocate Data Package Size Not In The Normal Range"
" , %d Out of [ %d , %d ] .",
size_package , Min_Package_Size , g_mmgr.max_block_size
);
struct memory_pool *pool=search_pool_for_enough_space(size_block);
if( pool == 0) pool = alloc_memory_pool();
return_val_if_fail(pool != 0 , 0);
return_val_if_fail(
Enough_Space_for_Alloc(pool,size_block),0);
struct descriptor *desptr = (struct descriptor*)pool->last;
pool->last += size_block;
return_val_if_fail(pool->last <= Pool_End(pool) , 0);
Set_Desptr(desptr,file,func,line,size_data);
int ret = desptr_add2_chain_active(desptr);
return_val_if_fail(ret == 0 , 0);
inc_alloc_data_stamp(size_data);
g_mmgr.allocate_from_pool_stamp++;
return Desptr_Entry_Ptr(desptr);
}
static void *alloc_from_chain_deactive(int size_data,
const char *file , const char *func , const int line)
{
return_val_if_fail(size_data >= Min_Data_Size,0,
"Data Size Lower Than %d .", size_data , Min_Data_Size);
int size_package = Data_Package_Size(size_data);
return_val_if_fail(
size_package >= Min_Package_Size
&& size_package <= g_mmgr.max_block_size,
0,
"Allocate Data Package Size Not In The Normal Range"
" , %d Out of [ %d , %d ] .",
size_package , Min_Package_Size , g_mmgr.max_block_size
);
struct memory_chain *chain=search_chain_for_data_size(size_data);
return_val_if_fail( chain!=0, 0 ,
"No Chain For Such Data Size %d ." , size_data);
struct descriptor *desptr=chain->deactive;
if(desptr == 0) return desptr;
chain->deactive=desptr->next;
Set_Desptr(desptr,file,func,line,size_data);
desptr_add2_chain_active(desptr);
g_mmgr.allocate_from_chain_stamp++;
inc_alloc_data_stamp(size_data);
return Desptr_Entry_Ptr(desptr);
}
void *memory_new(int size_data,
const char *file , const char *func , const int line)
{
err_msg(stdout,"/nAllocate Memory :");
err_msg(stdout,"/n<< : In %s %s Line %d , Alloc Size = %d .",
file , func , line , size_data);
if(g_mmgr.pool==0 && g_mmgr.large==0)
init_memory_manager();
if(size_data < Min_Data_Size) {
err_msg(stdout,"/n>> : Failed , Data Size %d Lower Than %d",
size_data , Min_Data_Size );
return 0;
}
int size_package = Data_Package_Size(size_data);
if( size_package < Min_Package_Size
|| size_package > Max_Large_Size){
err_msg(stdout,"/n>> : Failed , Package Size Not Normal"
" , %d Out of [ %d , %d ] .",
size_package , Min_Package_Size , Max_Large_Size);
return 0;
}
void *ptr=0;
if(size_package > g_mmgr.max_block_size
&& size_package <= Max_Large_Size ){
ptr=alloc_from_large(size_data,file,func,line);
err_msg(stdout,"/n>> : %s , From Large "
", Addr = %p , Pkg_Size = %d ." ,
ptr ? "Succeed" : "Failed" , ptr , size_package );
return ptr;
}
struct descriptor *desptr = 0 ;
struct memory_chain *chain = 0;
ptr=alloc_from_chain_deactive(size_data,file,func,line);
if(ptr != 0) {
desptr = Ptr_Entry_Desptr(ptr);
chain=search_chain_for_desptr(desptr);
if(chain == 0) {
err_msg(stdout,"/n>> : Failed , Allocate Process Exception .");
return 0;
}
err_msg(stdout,"/n>> : Succeed , From Chain "
", Addr = %p , Pkg_Size = %d / %d / %d ." ,
ptr , desptr->size , size_package , chain->block_size );
return ptr;
}
D__
ptr=alloc_from_pool(size_data , file , func , line);
if(ptr != 0) {
desptr = Ptr_Entry_Desptr(ptr);
chain=search_chain_for_desptr(desptr);
if(chain == 0) {
err_msg(stdout,"/n>> : Failed , Allocate Process Exception .");
return 0;
}
err_msg(stdout,"/n>> : Succeed , From Pool "
", Addr = %p , Size = %d / %d / %d ." ,
ptr , desptr->size , size_package , chain->block_size );
return ptr;
}
err_msg(stdout,"/n>> : Failed , Allocate Process Exception .");
return ptr;
}
///
///
static int memory_free_large( struct descriptor *desptr,
const char *file , const char *func , const int line)
{
return_val_if_fail(desptr != 0 , -1);
#if 0
只有当在POOL中找不到时才会从Large中找,这时无法判定desptr是否是
合法内存,故不能随便引用desptr->size,可能导致异常
int size_package=Data_Package_Size(desptr->size);
return_if_fail(
size_package > g_mmgr.max_block_size,
-1,
"Desptr Not Large , Size Only %d",
desptr->size
);
#endif
struct descriptor **pp = search_large_for_desptr(desptr);
return_val_if_fail( pp && *pp==desptr , -1);
*pp = (*pp)->next ;
sys_free(desptr);
g_mmgr.large_count--;
return 0;
}
static int memory_free_chain_active(struct descriptor *desptr,
const char *file , const char *func , const int line)
{
return_val_if_fail(desptr != 0 , -1);
struct descriptor **pp=search_chain_active_for_desptr(desptr);
return_val_if_fail( pp!=0 && *pp == desptr , -1);
*pp = (*pp)->next;
desptr_add2_deactive(desptr);
return 0;
}
int memory_free(void *ptr ,
const char *file , const char *func , const int line)
{
err_msg(stdout,"/nRelease Memory :");
err_msg(stdout,"/n<< : In %s %s Line %d , Ptr Addr = %p . ",
file , func , line , ptr);
if(g_mmgr.pool==0 && g_mmgr.large==0)
init_memory_manager();
if(ptr==0) {
err_msg(stdout,"/n>> : Failed , Release Ptr is Null . ");
return -1;
}
struct descriptor *desptr = Ptr_Entry_Desptr(ptr);
struct memory_pool *pool = search_pool_for_desptr(desptr);
if(pool==0){
int ret=memory_free_large(desptr,file,func,line);
if(ret!=0){
err_msg(stdout,"/n>> : Failed , Addr = %p Not Exist .",ptr);
return -1;
}
/*
下面这句return 0极其重要,因为上面如果ret=0,那么断言不会出发,
就会向下执行,因为desptr在memory_free_large中已经释放了,所以
在调用下面的函数过程中会发生错误,下面memory_free_chain_active
后面也有一个return 0,一定要注意,这时return_if_fail类的断言很容易
出错的地方
*/
err_msg(stdout,"/n>> : Succeed , From Large , System Works Pretty Well .");
return 0;
}
int ret=memory_free_chain_active(desptr,file,func,line);
if(ret!=0){
err_msg(stdout,"/n>> : Failed , Addr = %p Not Exist .",ptr);
return -1;
}
err_msg(stdout,"/n>> : Succeed , From Chain , System Works Pretty Well .");
return 0;
}
///
///
void *memory_resize(void *ptr , int size_data,
const char *file , const char *func , const int line)
{
err_msg(stdout,"/nReallocate Memory :");
err_msg(stdout,"/n<< : In %s %s Line %d , "
"Addr = %p , New Size = %d . ",
file , func , line , ptr , size_data);
if(g_mmgr.pool==0 && g_mmgr.large==0)
init_memory_manager();
if(ptr==0) {
err_msg(stdout,"/n>> : Failed , Realloc Ptr is Null .");
return ptr;
}
struct descriptor *desptr=Ptr_Entry_Desptr(ptr);
struct memory_pool *pool=search_pool_for_desptr(desptr);
struct descriptor **pp_large=0;
struct descriptor **pp_chain=0;
int old_size=0;
int new_size=Data_Package_Size(size_data);
if(pool==0) {
D__
pp_large = search_large_for_desptr(desptr);
if(*pp_large != desptr ) {
err_msg(stdout,"/n>> : Failed , Addr = %p Not Exist .", ptr);
return ptr;
}
old_size=Data_Package_Size(desptr->size);
if(old_size >= new_size) {
err_msg(stdout,"/n>> : Succeed , Ptr Not Changed , "
"Original Size = %d .", desptr->size );
return ptr;
}
*pp_large = (*pp_large)->next;
}
else {
D__
struct memory_chain *chain=search_chain_for_desptr(desptr);
if(chain == 0) {
err_msg(stdout,"/n>> : Failed , Addr = %p Not Exist .",ptr);
return ptr;
}
D__
pp_chain = search_active_for_desptr(chain,desptr);
if( pp_chain == 0 || *pp_chain != desptr ) {
err_msg(stdout,"/n>> : Failed , Addr = %p Not Exist .",ptr);
return ptr;
}
D__
if(new_size <= chain->block_size) {
err_msg(stdout,"/n>> : Succeed , Ptr Not Changed Yet , "
"Chain Block Size = %d" , chain->block_size);
return ptr;
}
*pp_chain = (*pp_chain)->next;
}
void *new_ptr=memory_new(size_data,file,func,line);
struct descriptor *new_desptr = Ptr_Entry_Desptr(new_ptr);
D__
Show_Value(new_desptr->size,d);
if(new_ptr == 0) {
err_msg(stdout,"/n>> : Failed , Reallocate Process Exception .");
return ptr;
}
D__
memcpy(new_ptr , ptr , Min(desptr->size , size_data));
new_desptr = Ptr_Entry_Desptr(new_ptr);
if(pp_large != 0) {
D__
sys_free(desptr);
g_mmgr.large_count--;
}
else if(pp_chain != 0) {
D__
desptr_add2_deactive(desptr);
}
new_desptr = Ptr_Entry_Desptr(new_ptr);
err_msg(stdout,"/n>> : Succeed , Ptr Addr = %p . "
"System Works Pretty Well ." , new_ptr);
return new_ptr;
}
const char *memory_status_string(void *ptr)
{
return_val_if_fail(ptr!=0,0,"Ptr Null");
struct descriptor **pp;
struct descriptor *desptr = Ptr_Entry_Desptr(ptr);
D__
struct memory_pool *pool=search_pool_for_desptr(desptr);
D__
if(pool != 0) {
if((char*)desptr >= (char*)pool->last)
return "Memory_In_Pool";
D__
pp=search_chain_active_for_desptr(desptr);
if(pp != 0 && *pp != 0) return "Memory_Allocated";
D__
pp=search_chain_deactive_for_desptr(desptr);
if(pp != 0 && *pp != 0) return "Memory_Released";
return "Memory_Invalid";
}
D__
pp=search_large_for_desptr(desptr);
if(*pp) return "Memory_Allocated_In_Large";
return "Memory_Invalid";
}
static void memory_show_leaking(struct descriptor *desptr)
{
if(desptr==0) return;
fprintf(stdout, "/n>> : %s %s Line %d , "
"Ptr Addr = %p , Size = %d . ",
desptr->file , desptr->func , desptr->line ,
Desptr_Entry_Ptr(desptr) , desptr->size);
}
void memory_leaking(void)
{
int flag=0;
struct descriptor *desptr=g_mmgr.large;
struct descriptor *next;
for( ; desptr!=0 ;desptr = next) {
if(flag==0){
err_msg(stdout,"/nMemory Leaking Danger :");
flag=1;
}
next = desptr->next;
memory_show_leaking(desptr);
sys_free(desptr);
g_mmgr.large_count--;
}
int i;
struct memory_chain *chain=g_mmgr.chain;
for(i=0 ; i
for( desptr=chain[i].active ; desptr ; desptr=desptr->next) {
if(flag==0){
err_msg(stdout,"/nMemory Leaking Danger :");
flag=1;
}
memory_show_leaking(desptr);
}
struct memory_pool *pool=g_mmgr.pool,*next_pool;
for( ; pool ; pool = next_pool ) {
next_pool=pool->next;
sys_free(pool);
g_mmgr.pool_count--;
}
if(g_mmgr.large_count != 0)
err_msg(stdout,"/n>> : Strange Exception Exist , Large Count None Zero");
if(g_mmgr.pool_count != 0)
err_msg(stdout,"/n>> : Strange Exception Exist , Pool Count None Zero");
Zero_Memory(&g_mmgr);
err_msg(stdout,"/n");
}
void memory_show()
{
Show_Value(g_mmgr.large_count,d);
Show_Value(g_mmgr.pool_count,d);
Show_Value(g_mmgr.allocate_from_large_stamp,d);
Show_Value(g_mmgr.allocate_from_pool_stamp,d);
Show_Value(g_mmgr.allocate_from_chain_stamp,d);
Show_Value(g_mmgr.allocate_memory_stamp,lld);
Show_Value(g_mmgr.allocate_data_stamp,lld);
Show_Value(g_mmgr.ratio,lf);
}