446 lines
8.0 KiB
C
446 lines
8.0 KiB
C
|
|
||
|
#include <sys/types.h>
|
||
|
#include <unistd.h>
|
||
|
#include <string.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
|
||
|
|
||
|
#define Smem_included_by_smem_C
|
||
|
#include "smem.h"
|
||
|
|
||
|
|
||
|
|
||
|
/* ------------------------------ SmemiteM ----------------------------- */
|
||
|
|
||
|
|
||
|
int Smemitem_new(item,data,size,next,hash_start,flag)
|
||
|
struct SmemiteM **item;
|
||
|
char *data;
|
||
|
size_t size;
|
||
|
struct SmemiteM *next;
|
||
|
struct SmemiteM **hash_start;
|
||
|
int flag;
|
||
|
{
|
||
|
struct SmemiteM *t;
|
||
|
|
||
|
*item= t= (struct SmemiteM *) malloc(sizeof(struct SmemiteM));
|
||
|
if(t==NULL)
|
||
|
return(-1);
|
||
|
t->data= data;
|
||
|
t->size= size;
|
||
|
t->prev= NULL;
|
||
|
t->next= next;
|
||
|
|
||
|
#ifdef Smem_with_hasH
|
||
|
t->hash_next= NULL;
|
||
|
t->hash_prev= NULL;
|
||
|
#endif /* Smem_with_hasH */
|
||
|
|
||
|
if(next!=NULL) {
|
||
|
if(next->prev!=NULL) {
|
||
|
t->prev= next->prev;
|
||
|
next->prev->next= t;
|
||
|
}
|
||
|
next->prev= t;
|
||
|
}
|
||
|
|
||
|
#ifdef Smem_with_hasH
|
||
|
if(hash_start!=NULL) {
|
||
|
t->hash_next= *hash_start;
|
||
|
if(t->hash_next!=NULL) {
|
||
|
t->hash_next->hash_prev= t;
|
||
|
}
|
||
|
*hash_start= t;
|
||
|
}
|
||
|
#endif /* Smem_with_hasH */
|
||
|
|
||
|
return(1);
|
||
|
}
|
||
|
|
||
|
|
||
|
int Smemitem_destroy(in_item,hash_start,flag)
|
||
|
struct SmemiteM **in_item;
|
||
|
struct SmemiteM **hash_start;
|
||
|
int flag;
|
||
|
{
|
||
|
struct SmemiteM *item;
|
||
|
|
||
|
item= *in_item;
|
||
|
if(item==NULL)
|
||
|
return(0);
|
||
|
if(item==Smem_start_iteM)
|
||
|
Smem_start_iteM= item->next;
|
||
|
if(item->prev!=NULL)
|
||
|
item->prev->next= item->next;
|
||
|
if(item->next!=NULL)
|
||
|
item->next->prev= item->prev;
|
||
|
|
||
|
#ifdef Smem_with_hasH
|
||
|
if(hash_start!=NULL) {
|
||
|
if(item==*hash_start)
|
||
|
*hash_start= item->hash_next;
|
||
|
if(item->hash_prev!=NULL)
|
||
|
item->hash_prev->hash_next= item->hash_next;
|
||
|
if(item->hash_next!=NULL)
|
||
|
item->hash_next->hash_prev= item->hash_prev;
|
||
|
}
|
||
|
#endif /* Smem_with_hasH */
|
||
|
|
||
|
free((char *) item);
|
||
|
*in_item= NULL;
|
||
|
return(1);
|
||
|
}
|
||
|
|
||
|
|
||
|
int Smemitem_report(item,line,flag)
|
||
|
struct SmemiteM *item;
|
||
|
char line[1024];
|
||
|
int flag;
|
||
|
{
|
||
|
char *cpt;
|
||
|
int i,upto;
|
||
|
|
||
|
sprintf(line,"%4lu bytes at %8.8lx ",(unsigned long) item->size,
|
||
|
(unsigned long) item->data);
|
||
|
cpt= line+strlen(line);
|
||
|
if(item->size<=256)
|
||
|
upto= item->size;
|
||
|
else
|
||
|
upto= 256;
|
||
|
if(item->data!=NULL) {
|
||
|
strcpy(cpt,"= \"");
|
||
|
cpt+= 3;
|
||
|
for(i=0;i<upto;i++){
|
||
|
if(item->data[i]<32 || item->data[i]>=127 || item->data[i]=='\\') {
|
||
|
sprintf(cpt,"\\%2.2X",(unsigned char) item->data[i]);
|
||
|
cpt+= 3;
|
||
|
} else {
|
||
|
*(cpt++)= item->data[i];
|
||
|
}
|
||
|
}
|
||
|
if(i<item->size) {
|
||
|
sprintf(cpt,"\" [truncated]");
|
||
|
} else {
|
||
|
*(cpt++)= '"';
|
||
|
*cpt= 0;
|
||
|
}
|
||
|
}
|
||
|
return(1);
|
||
|
}
|
||
|
|
||
|
|
||
|
int Smemitem_stderr(item,flag)
|
||
|
struct SmemiteM *item;
|
||
|
int flag;
|
||
|
{
|
||
|
char line[1024];
|
||
|
Smemitem_report(item,line,0);
|
||
|
fprintf(stderr,"%s\n",line);
|
||
|
return(1);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/* -------------------------------- Smem ------------------------------ */
|
||
|
|
||
|
|
||
|
int Smem_protest(line,flag)
|
||
|
char *line;
|
||
|
int flag;
|
||
|
{
|
||
|
fprintf(stderr,"%s\n",line);
|
||
|
return(1);
|
||
|
}
|
||
|
|
||
|
|
||
|
int Smem_hashindex(ptr,flag)
|
||
|
char *ptr;
|
||
|
int flag;
|
||
|
{
|
||
|
unsigned long idx;
|
||
|
|
||
|
idx= (unsigned long) ptr;
|
||
|
return((idx>>Smem_hashshifT)%(Smem_hashsizE));
|
||
|
}
|
||
|
|
||
|
|
||
|
/* find a certain memory item */
|
||
|
struct SmemiteM *Smem_find_item(ptr,flag)
|
||
|
char *ptr;
|
||
|
int flag;
|
||
|
{
|
||
|
int misscount= 0,idx;
|
||
|
struct SmemiteM *current;
|
||
|
|
||
|
#ifdef Smem_with_hasH
|
||
|
|
||
|
idx= Smem_hashindex(ptr,0);
|
||
|
for(current= Smem_hasH[idx];current!=NULL;current= current->hash_next) {
|
||
|
if(current->data==ptr)
|
||
|
return(current);
|
||
|
misscount++;
|
||
|
}
|
||
|
|
||
|
#else /* Smem_with_hasH */
|
||
|
|
||
|
for(current= Smem_start_iteM;current!=NULL;current= current->next) {
|
||
|
if(current->data==ptr)
|
||
|
return(current);
|
||
|
misscount++;
|
||
|
}
|
||
|
|
||
|
#endif /* ! Smem_with_hasH */
|
||
|
|
||
|
return(NULL);
|
||
|
}
|
||
|
|
||
|
|
||
|
int Smem_search_and_delete(ptr,flag)
|
||
|
char *ptr;
|
||
|
int flag;
|
||
|
/*
|
||
|
bit0= revoke registration : decrement counters
|
||
|
*/
|
||
|
{
|
||
|
int idx;
|
||
|
struct SmemiteM *current;
|
||
|
|
||
|
current= Smem_find_item(ptr,0);
|
||
|
if(current==NULL)
|
||
|
return(0);
|
||
|
Smem_record_counT--;
|
||
|
Smem_record_byteS-= current->size;
|
||
|
idx= Smem_hashindex(ptr,0);
|
||
|
Smemitem_destroy(¤t,&(Smem_hasH[idx]),0);
|
||
|
Smem_hash_counteR[idx]-= 1.0;
|
||
|
if(flag&1) {
|
||
|
Smem_malloc_counT--;
|
||
|
Smem_pending_counT--;
|
||
|
}
|
||
|
return(1);
|
||
|
}
|
||
|
|
||
|
|
||
|
char *Smem_malloc(size)
|
||
|
size_t size;
|
||
|
{
|
||
|
int idx;
|
||
|
char *cpt;
|
||
|
|
||
|
if(size==0) {
|
||
|
Smem_protest("########### smem.c : malloc(0) caught",0);
|
||
|
return(NULL);
|
||
|
}
|
||
|
|
||
|
/* if(size==1032)
|
||
|
cpt= NULL; / * set breakpoint here to find requests of certain size */
|
||
|
|
||
|
cpt= (char *) malloc(size);
|
||
|
if(cpt==NULL) {
|
||
|
char text[161];
|
||
|
sprintf(text,"########### smem.c : malloc( %lu ) returned NULL",
|
||
|
(unsigned long) size);
|
||
|
Smem_protest(text,0);
|
||
|
return(NULL);
|
||
|
}
|
||
|
/* if(cpt==0x080a1e20)
|
||
|
cpt= NULL; / * set breakpoint here to find origin of certain address */
|
||
|
|
||
|
Smem_malloc_counT++;
|
||
|
Smem_pending_counT++;
|
||
|
if(Smem_record_itemS) {
|
||
|
idx= Smem_hashindex(cpt,0);
|
||
|
Smem_hash_counteR[idx]+= 1.0;
|
||
|
if(Smemitem_new(&Smem_start_iteM,cpt,size,Smem_start_iteM,
|
||
|
&(Smem_hasH[idx]),0)<=0) {
|
||
|
Smem_protest(
|
||
|
"########### smem.c : malloc( sizeof(SmemiteM) ) returned NULL",0);
|
||
|
return(NULL);
|
||
|
}
|
||
|
Smem_record_counT++;
|
||
|
Smem_record_byteS+= size;
|
||
|
}
|
||
|
return(cpt);
|
||
|
}
|
||
|
|
||
|
|
||
|
int Smem_free(ptr)
|
||
|
char *ptr;
|
||
|
{
|
||
|
if(ptr==NULL) {
|
||
|
Smem_protest("########### smem.c : free() of NULL pointer caught",0);
|
||
|
return(0);
|
||
|
}
|
||
|
if(Smem_record_itemS) {
|
||
|
if(Smem_search_and_delete(ptr,0)<=0) {
|
||
|
Smem_protest("########### smem.c : free() of unrecorded pointer caught",0);
|
||
|
return(0);
|
||
|
}
|
||
|
}
|
||
|
Smem_free_counT++;
|
||
|
Smem_pending_counT--;
|
||
|
free(ptr);
|
||
|
return(1);
|
||
|
}
|
||
|
|
||
|
|
||
|
int Smem_report(line,flag)
|
||
|
char line[1024];
|
||
|
int flag;
|
||
|
{
|
||
|
sprintf(line,"malloc= %.f , free= %.f , pending= %.f",
|
||
|
Smem_malloc_counT,Smem_free_counT,Smem_pending_counT);
|
||
|
if(Smem_record_itemS) {
|
||
|
sprintf(line+strlen(line)," , bytes=%.f , records= %.f",
|
||
|
Smem_record_byteS,Smem_record_counT);
|
||
|
}
|
||
|
return(1);
|
||
|
}
|
||
|
|
||
|
|
||
|
int Smem_stderr(flag)
|
||
|
int flag;
|
||
|
/*
|
||
|
bit0= report 50 youngest pending items too
|
||
|
bit1= do not report if nothing is pending
|
||
|
*/
|
||
|
{
|
||
|
struct SmemiteM *current;
|
||
|
char line[1024];
|
||
|
int i= 0;
|
||
|
|
||
|
if(flag&2)
|
||
|
if(Smem_pending_counT==0.0
|
||
|
&& Smem_record_counT==0.0
|
||
|
&& Smem_record_byteS==0.0)
|
||
|
return(2);
|
||
|
Smem_report(line,0);
|
||
|
fprintf(stderr,"%s\n",line);
|
||
|
if(flag&1) {
|
||
|
for(current= Smem_start_iteM;current!=NULL;current= current->next) {
|
||
|
Smemitem_stderr(current,0);
|
||
|
if(++i>=50)
|
||
|
break;
|
||
|
}
|
||
|
if(current!=NULL)
|
||
|
if(current->next!=NULL)
|
||
|
fprintf(stderr,"[list truncated]\n");
|
||
|
}
|
||
|
return(1);
|
||
|
}
|
||
|
|
||
|
|
||
|
int Smem_set_record_items(value)
|
||
|
int value;
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
if(!Smem_hash_initializeD) {
|
||
|
for(i=0;i<Smem_hashsizE;i++) {
|
||
|
Smem_hasH[i]= NULL;
|
||
|
Smem_hash_counteR[i]= 0.0;
|
||
|
}
|
||
|
Smem_hash_initializeD= 1;
|
||
|
}
|
||
|
Smem_record_itemS= value;
|
||
|
return(1);
|
||
|
}
|
||
|
|
||
|
|
||
|
int Smem_is_recorded(ptr,flag)
|
||
|
char *ptr;
|
||
|
int flag;
|
||
|
/*
|
||
|
bit0= complain if return(0)
|
||
|
*/
|
||
|
{
|
||
|
if(Smem_record_itemS==0)
|
||
|
return(2);
|
||
|
if(Smem_find_item(ptr,0)!=NULL)
|
||
|
return(1);
|
||
|
if(flag&1)
|
||
|
Smem_protest("########### smem.c : free() of unrecorded pointer caught",0);
|
||
|
return(0);
|
||
|
}
|
||
|
|
||
|
|
||
|
/* A simple C string cloner */
|
||
|
int Smem_clone_string(ptr,text)
|
||
|
char **ptr;
|
||
|
char *text;
|
||
|
{
|
||
|
*ptr= Smem_malloC(strlen(text)+1);
|
||
|
if(*ptr==NULL)
|
||
|
return(-1);
|
||
|
strcpy(*ptr,text);
|
||
|
return(1);
|
||
|
}
|
||
|
|
||
|
|
||
|
/* ----------------- for usage via debugger commands --------------------- */
|
||
|
|
||
|
|
||
|
/* find a certain memory item */
|
||
|
struct SmemiteM *Smem_find_data(ptr)
|
||
|
char *ptr;
|
||
|
{
|
||
|
return(Smem_find_item(ptr,0));
|
||
|
}
|
||
|
|
||
|
|
||
|
/* browsing the list */
|
||
|
struct SmemiteM *Smem_fetch_item(step,flag)
|
||
|
int step;
|
||
|
int flag;
|
||
|
/*
|
||
|
bit0= reset cursor (and therefore address absolutely)
|
||
|
*/
|
||
|
{
|
||
|
static struct SmemiteM *current= NULL;
|
||
|
|
||
|
if((flag&1)||current==NULL)
|
||
|
current= Smem_start_iteM;
|
||
|
if(step>0) {
|
||
|
for(;current!=NULL;current= current->next) {
|
||
|
if(step==0)
|
||
|
return(current);
|
||
|
step--;
|
||
|
}
|
||
|
} else if(step<0) {
|
||
|
for(;current!=NULL;current= current->prev) {
|
||
|
if(step==0)
|
||
|
return(current);
|
||
|
step++;
|
||
|
}
|
||
|
} else {
|
||
|
return(current);
|
||
|
}
|
||
|
return(NULL);
|
||
|
}
|
||
|
|
||
|
|
||
|
int Smem_print_hash_counter() {
|
||
|
int i;
|
||
|
|
||
|
for(i=0;i<Smem_hashsizE;i++)
|
||
|
printf("%4d : %10.f\n",i,Smem_hash_counteR[i]);
|
||
|
return(1);
|
||
|
}
|
||
|
|
||
|
|
||
|
/* delete all recorded memory items */
|
||
|
int Smem_delete_all_items()
|
||
|
{
|
||
|
int ret;
|
||
|
|
||
|
while(Smem_start_iteM!=NULL) {
|
||
|
ret= Smem_free(Smem_start_iteM->data);
|
||
|
if(ret<=0)
|
||
|
return(0);
|
||
|
}
|
||
|
return(1);
|
||
|
}
|
||
|
|
||
|
|