C
cs
This is the function malloc_m() that should be like malloc() but it
should find memory leak, and over bound writing in arrays.
How many errors do you see?
Thank you
********************************************
/* mallocm.c */
/* funzione di libreria per trattamento della memoria e rilevamento
errori */
/* uso: c_compiler malloc.c e usare malloc .obj */
/*
Declino ogni responsabilita' per qualsiasi danno
che potrebbe arrecare questo programma e ogni
garanzia che serva a qualche cosa; Il programma si
intende libero (free) per l'uso e per il
cambiamento.
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/* MEM_LIMIT e' il limite del numero di diversi puntatori
ritornati da malloc_m */
#define MEM_LIMIT 100000
#define MAX_ARRAYS 255
#define UNS unsigned
/*************************CCCCCCC**********************************/
#ifdef __cplusplus
extern "C" {
#endif
static unsigned yuyuy=0;
typedef double Align; /* per allineare alla double */
union header { /* header del blocco */
struct {union header* ptr; /* blocco successivo in free list */
unsigned size; /* dimensione di questo blocco */
}s;
Align x; /* forza l'allineamento dei blocchi */
};
typedef union header Header;
static Header base; /* lista vuota per iniziare */
static Header *freep=NULL; /* inizio della free list */
char name_ [ 1100 ] = {0}; /* name_== nome routines chiamate
*/
char memo_ [ 300 ] = {0}; /* stringa ove errori trovati in
memoria */
int n_i_ = 0 ;
int libero_m_ = 0 ; /* libero_m_==1 controllo tutti i
vettori a
ogni chiamate di free(); serve insieme a name_ per individuare le
routines che
sovrascrivono la memoria che non hanno (e.g. if(libero_m_)
init_w("nome_routines") */
typedef struct {
void *p;
unsigned size;
unsigned piu;
unsigned meno;
}vettore_array;
static vettore_array **p_p_p_=0; /* lista di struct di puntatori
ritornati da malloc_m */
static unsigned i_i_i_=0; /* attuale indice nella lista */
static unsigned m_m_m_=0; /* massimo indice nella lista */
static char **list_ =0; /* lista dei vettori richiesti al
sys */
static unsigned list_i_=0;
static unsigned list_m_=0;
static int mem_init(unsigned siz)
{vettore_array **pp;
unsigned j;
/*---------------------*/
//printf("p_p_p_=%p i_i_i_==%u siz=%u ", (void*) p_p_p_, i_i_i_,
siz );
if(p_p_p_==0)
{pp= (vettore_array**) malloc( (siz+1) * sizeof *pp );
if(pp==0) return 0;
for( j=0; j<siz; ++j)
{pp[j]= (vettore_array*) malloc( sizeof(vettore_array) );
if(pp[j]==0)
{if(j!=0)
for( --j ; j!=0 ; --j)
free( (void*) pp[j] );
free((void*) pp[0]); free((void*) pp); return 0;
}
}
}
else { if(siz==m_m_m_) return 1;
else if(siz < m_m_m_) /* dovrebbe distruggere la
memoria eccessiva */
{ if(siz<=i_i_i_) return 1; /* la 1024ma volta che viene
chiamato free_m()*/
for(j=siz; j<m_m_m_; ++j) // v[0]...v[size]=size+1
free((void*) p_p_p_[j]);
pp=(vettore_array**) realloc(p_p_p_, (siz + 1) * sizeof
*pp );
if(pp==0) {printf("Fallimento realloc\n"); m_m_m_ =
siz; return 1;}
/* ritorna senza cambiare niente */
goto label;
}
pp= (vettore_array**) realloc( (void*) p_p_p_, (siz + 1) *
sizeof *pp);
if(pp==0) {printf("Fallimento realloc\n"); return 0;}
if( siz > i_i_i_)
{ for( j=i_i_i_; j<siz; ++j)
{pp[j]= (vettore_array*) malloc(
sizeof(vettore_array) );
if(pp[j]==0)
{if(j!=0)
for( --j ; j!=0 ; --j)
free( (void*) pp[j] );
free((void*) pp[0]); return 0;
}
}
}
}
label: ;
m_m_m_ = siz; p_p_p_=pp; return 1;
}
/* malloc_m: allocatore di memoria */
void* malloc_m(unsigned nbytes)
{Header *p, *prevp;
unsigned nunits, *k, *kk, led, size;
Header* morecore(unsigned);
unsigned verifica_all_m( void );
void stato_mem(void);
/*-------------------------------*/
if(libero_m_)
{
if(verifica_all_m()==0)
stato_mem();
}
if(i_i_i_>MEM_LIMIT || nbytes==0 ) return 0;
if(i_i_i_>=m_m_m_)
{if(mem_init( i_i_i_ + MAX_ARRAYS ) == 0) return 0;}
nunits = nbytes + sizeof(Header);
nunits = nunits/sizeof(Header) + (( nunits%sizeof(Header)
{ base.s.ptr=freep=prevp=&base; base.s.size=0; }
for(p=prevp->s.ptr; ; prevp=p, p=p->s.ptr)
{if(p->s.size>=nunits) /* spazio insufficiente */
{if(p->s.size==nunits) /* esattamente */
{
prevp->s.ptr = p->s.ptr;
}
else /* alloca la parte finale */
{
p->s.size -= nunits;
p += p->s.size;
p->s.size =nunits;
}
freep = prevp;
/****************** Blocco aggiunto ************/
size = nbytes;
led = (size % sizeof(unsigned)!=0) ? 1: 0;
k = (unsigned*)(p+1); kk=k; --k;
p_p_p_[i_i_i_]->meno = *k;
p_p_p_[i_i_i_]->piu = kk[size/sizeof(unsigned)+ led];
p_p_p_[i_i_i_]->size = size;
p_p_p_[i_i_i_++]->p = (void*)(p+1);
/***********************************************/
return (void*) (p+1);
}
if(p==freep) /* la free list e' terminata */
{++yuyuy; /* numero delle volte di mem.
richieste al sistema */
if((p=morecore(nunits)) == NULL)
return NULL; /* non c'e' piu' spazio */
}
}
}
/* Ritorna il numero degli elementi;
se il numero degli elementi e' 0 ritorna (unsigned) -1
se errori ritorna 0 */
unsigned verifica_all_m( void )
{unsigned j, *k, *kk, xk, xkk, led;
/*----------------*/
if( p_p_p_==0 || i_i_i_==0 ) return -1;
for(j=0 ; j < i_i_i_ ; ++j)
{k = (unsigned*) (p_p_p_[j]->p); kk=k; --k;
led = (p_p_p_[j]->size % sizeof(unsigned)!=0) ? 1: 0;
if( (xk=kk[p_p_p_[j]->size/sizeof(unsigned) + led]) !=
(xkk=p_p_p_[j]->piu) )
{
/* nota bene: n:v significa NUOVO VALORE : VECCHIO VALORE */
sprintf(memo_ , "verifica_all_mMEM_+ p=%5p size=%5u p[-1]=%5u
p[max]=%5u n:v=%5u:%5u",
p_p_p_[j]->p, p_p_p_[j]->size, p_p_p_[j]->meno,
xkk, xk, xkk);
if(n_i_>2) name_[ n_i_ - 2 ]='+';
return 0;
}
if( (xk=*k) != (xkk=p_p_p_[j]->meno) )
{ sprintf(memo_ , "verifica_all_mMEM_- p=%5p size=%5u
p[-1]=%5u p[max]=%5u n:v=%5u:%5u",
p_p_p_[j]->p, p_p_p_[j]->size, xkk,
p_p_p_[j]->piu, xk, xkk);
if(n_i_>2) name_[n_i_ - 2]='-';
return 0;
}
}
return i_i_i_;
}
void verifica_all( void )
{if(verifica_all_m( )==0)
{printf("Errore nella memoria\n");
printf("memo=%s name=%s\n", memo_, name_ );
}
}
/* ritorna 0 se il vettore fa parte della lista
se pointer==0 ritorna 1 se tutto e' cancellato
2 se tutto e' cancellato tranne il puntatore iniziale
3 altrimenti
*/
unsigned verifica_m( void* pointer, unsigned *jj)
{unsigned j, *k, *kk, xk, xkk, led;
/*----------------*/
if(jj!=0) *jj=0;
if(pointer==0)
{if( i_i_i_==0 && p_p_p_==0 ) return 1;
else if(i_i_i_==0) return 2;
else return 3;
}
if(p_p_p_==0 ) return 1;
for(j=0 ; j < i_i_i_ ; ++j)
if( p_p_p_[j]->p == pointer ) break;
if(j==i_i_i_ ) {printf("verifica_mMEM_0 %p indice=%u memo=%s
name=%s\n", pointer, i_i_i_, memo_, name_ );
if(n_i_>2) name_[n_i_ -2]='0'; return 7;
}
k = (unsigned*) pointer; kk=k; --k;
led = (p_p_p_[j]->size % sizeof(unsigned)!=0) ? 1: 0;
*jj=j;
if( (xk=kk[p_p_p_[j]->size/sizeof(unsigned) + led]) !=
(xkk=p_p_p_[j]->piu) )
{ printf("p=%p size=%u p[-1]=%u p[max]=%u ", pointer,
p_p_p_[j]->size, *k, xk);
printf("verifica_mMEM_+ n:v>%u:%u\n", xk, xkk);
if(n_i_>2) name_[ n_i_ - 2 ]='+';
return 8;
}
if( (xk=*k) != (xkk=p_p_p_[j]->meno) )
{ printf("p=%p size=%u p[-1]=%u p[max]=%u ", pointer,
p_p_p_[j]->size, xkk, p_p_p_[j]->piu);
printf("verifica_mMEM_- n:v>%u:%u\n", xk, xkk);
if(n_i_>2) name_[n_i_ - 2]='-';
return 9;
}
else return 0;
}
unsigned verifica_p_m( void* pointer)
{unsigned jj;
return verifica_m( pointer, &jj);
}
static void free_list_m(void)
{while( list_i_ !=0 )
{--list_i_; free(list_[list_i_]);}
free(list_); list_=0; list_m_=0; freep=NULL;
}
static void free_vettore_m(void)
{if(p_p_p_==0) { m_m_m_=0; i_i_i_=0; return;}
while( i_i_i_ !=0 )
{--i_i_i_; free((void*) p_p_p_[i_i_i_]); }
free((void*) p_p_p_);
p_p_p_=0; m_m_m_=0;
}
static void inserisci(void* ap, unsigned jk, unsigned j)
{Header *bp, *p;
static unsigned f_cont=0;
/*-------------------*/
if(jk==0) ++f_cont;
bp = (Header*)ap - 1; /* punta all'header del blocco */
for( p=freep; !(bp>p && bp < p->s.ptr); p=p->s.ptr )
if( p >= p->s.ptr && (bp>p || bp < p->s.ptr) )
break; /* il blocco liberato e'
ad un estremo della lista*/
if(jk) goto label;
/********************************************/
if(j != i_i_i_ - 1)
{
p_p_p_[j]->p = p_p_p_[i_i_i_ - 1]->p;
p_p_p_[j]->size = p_p_p_[i_i_i_ - 1]->size;
p_p_p_[j]->meno = p_p_p_[i_i_i_ - 1]->meno;
p_p_p_[j]->piu = p_p_p_[i_i_i_ - 1]->piu;
}
p_p_p_[--i_i_i_]->p =0; p_p_p_[i_i_i_]->size=0;
p_p_p_[i_i_i_]->meno=0; p_p_p_[i_i_i_]->piu =0;
if(m_m_m_>1000 && f_cont%1024==0)
mem_init(i_i_i_+64);
/***********************************************/
label:
if(bp+bp->s.size == p->s.ptr)/*lo unisce al blocco dopo*/
{bp->s.size += p->s.ptr->s.size;
bp->s.ptr = p->s.ptr->s.ptr;
}
else bp->s.ptr=p->s.ptr;
if(p+p->s.size == bp)/* lo unisce al blocco prima*/
{p->s.size += bp->s.size;
p->s.ptr = bp->s.ptr;
}
else p->s.ptr=bp;
freep = p;
}
void free_all_m(void) {free_vettore_m(); free_list_m();}
/*Non usare free_all_m() ma free_a_i_m se ci sono oggetti
allocati da costruttori e distruttori del c++
(gli oggetti fuori da una qualsiasi procedura finiscono quando si
chiude
l'ultima istruzione del main) */
void free_a_i_m(void)
{if(i_i_i_==0)
{free_vettore_m(); free_list_m(); printf("MEMORIA DINAMICA
LIBERATA\n"); }
}
#define NALLOC 1024 /* numero minimo di unita' richieste */
/* morecore: chiede al sistema memoria aggiuntiva */
static Header* morecore(unsigned nu)
{char *cp, **p;
Header *up;
unsigned len;
/*-----------------------*/
if(nu<NALLOC) nu=NALLOC;
cp = (char*) malloc(nu * sizeof(Header));
if( cp==0 ) /* non c'e' piu' spazio */
return NULL;
if(list_i_ <= list_m_ )
{len = (list_m_==0 ? 128: 2*list_m_);
p = (char**) realloc(list_, len * sizeof *p);
if(p==0)
{free(cp); return 0;}
list_ = p;
list_m_ =len;
}
list_[list_i_++]=cp;
up=(Header*) cp;
up->s.size=nu;
inserisci((void*)(up+1), 1, 0);
return freep;
}
/* se pointer!=0 ritorna la size del pointer
ritorna 0 se il pointer non c'e' */
unsigned get_size_m( void* pointer )
{unsigned j;
/*----------------*/
if(pointer==0 || p_p_p_==0) return 0;
for(j=0 ; j < i_i_i_ ; ++j)
if( p_p_p_[j]->p == pointer ) break;
if(j==i_i_i_ ) return 0;
return p_p_p_[j]->size;
}
void init_w(const char *nam)
{unsigned i, j;
/*---------------------*/
if(nam==0) return;
if( n_i_ > 2 )
name_[n_i_ - 1]='|';
if( n_i_ >= 1016 ) // 0..14 carattere 15='|'
n_i_=0;
for(i=n_i_, j=0; j<15 && nam[j]!=0; ++i, ++j)
name_=nam[j];
for( ; j< 15; ++i, ++j)
name_=' ';
name_ = '#';
n_i_ += 16;
}
void leggi_mem(void)
{Header *u, *v;
unsigned j;
for( u = freep; u!=0 ; )
{printf("|v=%u s=%u|", (unsigned)u / sizeof(Header), u->s.size );
if(u->s.ptr==freep) break;
v=u->s.ptr;
if((u + u->s.size) != v)
{j = (UNS)(v-u) - u->s.size;
if(j<123456)
printf("%u", j );
else printf("#");
}
u=v;
}
}
void stato_mem(void)
{unsigned j;
leggi_mem();
fflush(stdout);
printf("\nRAPPORTO MEMORIA DINAMICA. ");
printf("Memoria richiesta al sistema=%u volte. ", yuyuy);
j=verifica_all_m();
if(j!=0 && j!=-1) printf("%u vettori allocati con successo\n", j);
else {if(j==0) goto label;
printf("Tutto bene. ");
j=verifica_m(0, 0);
if(j==1) printf("Sia la base sia il contatore sono NULLI\n");
else if(j==2) printf("Il contatore e' nullo ma la base no\n");
else {label: ;
printf("Errore nella memoria\n");
printf("memo=%s name=%s\n", memo_, name_ );
free_vettore_m(); free_list_m();
exit(0);
}
}
}
void controlla_m(char* st)
{printf("!%s!", st);
fflush(stdout);
if(verifica_all_m()==0)
{if(st) printf("ERRORE!");
fflush(stdout);
stato_mem();
}
}
/* free: inserisce in free list il blocco ap */
void free_m(void* ap)
{ unsigned j;
/*-------------------*/
if(ap==0) return ;
if(libero_m_)
{
if(verifica_all_m()==0)
stato_mem();
}
if(verifica_m(ap, &j))
{ printf("free_m(): "); stato_mem();
free_vettore_m(); free_list_m();
exit(0);
}
inserisci(ap, 0, j);
}
void stampa_chiamate(void){printf("memo=%s name=%s\n", memo_, name_
);}
#ifdef __cplusplus
}
#endif
// fine di extern C
/*************************CCCCCCC**********************************/
/* file.c che utilizza malloc_m()
c_compiler file.c mallocm.obj */
#include <stdio.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
void* malloc_m(unsigned nbytes);
unsigned verifica_all_m( void );
unsigned verifica_m( void* pointer, unsigned *jj);
unsigned verifica_p_m( void* pointer);
void free_m(void* ap);
void free_all_m(void);
void free_a_i_m(void);
unsigned get_size_m( void* pointer );
void stato_mem(void);
void leggi_mem(void);
void controlla_m(char* st);
void verifica_all( void );
void init_w(const char *nam);
void stampa_chiamate(void);
#ifdef __cplusplus
}
#endif
extern int libero_m_ ;
void g(void)
{char *r;
/**********************/
if(libero_m_) init_w("g() ");
r=malloc_m(100*sizeof(*r));
r[-1]='8'; /* errore per r[-1] */
/* errore non liberato r */
// free_m(r);
/* errore se non uso free_m(r) ed stato_mem() in main mi dice
"RAPPORTO MEMORIA DINAMICA. Memoria richiesta al sistema=1 volte.
1 vettori allocati con successo "
significa che mi sono dimenticato di cancellare un vettore
*/
}
void f(void)
{char *p;
int i;
/*********************/
if(libero_m_) init_w("f() ");
p=malloc_m(100*sizeof(*p));
for(i=0; i<110; ++i) p='0'; /* errore per i>=100 */
free_m(p); /* se libero_m_ = 1; identifica routine dell'errore */
/* se libero_m_ = 0; (default) identifica un errore */
g();
}
int main(void)
{// libero_m_ = 1; // scrive routines ove e' identificato l'errore
// se si identifica errore => "libero_m_ = 1;"
// nel codice normale ove non si identificano errori *non* si
// deve scrivere "libero_m_ = 1;"
if(libero_m_) init_w("main");
f();
stato_mem(); /* identifica eventuali errori e "momory leaks"*/
free_all_m(); /* si deve usare prima di uscire dal programma */
stato_mem(); /* se succede
"RAPPORTO MEMORIA DINAMICA. Memoria richiesta al sistema=1 volte.
Tutto bene. Sia
la base sia il contatore sono NULLI"
tutto sembra ok */
return 0;
}
should find memory leak, and over bound writing in arrays.
How many errors do you see?
Thank you
********************************************
/* mallocm.c */
/* funzione di libreria per trattamento della memoria e rilevamento
errori */
/* uso: c_compiler malloc.c e usare malloc .obj */
/*
Declino ogni responsabilita' per qualsiasi danno
che potrebbe arrecare questo programma e ogni
garanzia che serva a qualche cosa; Il programma si
intende libero (free) per l'uso e per il
cambiamento.
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/* MEM_LIMIT e' il limite del numero di diversi puntatori
ritornati da malloc_m */
#define MEM_LIMIT 100000
#define MAX_ARRAYS 255
#define UNS unsigned
/*************************CCCCCCC**********************************/
#ifdef __cplusplus
extern "C" {
#endif
static unsigned yuyuy=0;
typedef double Align; /* per allineare alla double */
union header { /* header del blocco */
struct {union header* ptr; /* blocco successivo in free list */
unsigned size; /* dimensione di questo blocco */
}s;
Align x; /* forza l'allineamento dei blocchi */
};
typedef union header Header;
static Header base; /* lista vuota per iniziare */
static Header *freep=NULL; /* inizio della free list */
char name_ [ 1100 ] = {0}; /* name_== nome routines chiamate
*/
char memo_ [ 300 ] = {0}; /* stringa ove errori trovati in
memoria */
int n_i_ = 0 ;
int libero_m_ = 0 ; /* libero_m_==1 controllo tutti i
vettori a
ogni chiamate di free(); serve insieme a name_ per individuare le
routines che
sovrascrivono la memoria che non hanno (e.g. if(libero_m_)
init_w("nome_routines") */
typedef struct {
void *p;
unsigned size;
unsigned piu;
unsigned meno;
}vettore_array;
static vettore_array **p_p_p_=0; /* lista di struct di puntatori
ritornati da malloc_m */
static unsigned i_i_i_=0; /* attuale indice nella lista */
static unsigned m_m_m_=0; /* massimo indice nella lista */
static char **list_ =0; /* lista dei vettori richiesti al
sys */
static unsigned list_i_=0;
static unsigned list_m_=0;
static int mem_init(unsigned siz)
{vettore_array **pp;
unsigned j;
/*---------------------*/
//printf("p_p_p_=%p i_i_i_==%u siz=%u ", (void*) p_p_p_, i_i_i_,
siz );
if(p_p_p_==0)
{pp= (vettore_array**) malloc( (siz+1) * sizeof *pp );
if(pp==0) return 0;
for( j=0; j<siz; ++j)
{pp[j]= (vettore_array*) malloc( sizeof(vettore_array) );
if(pp[j]==0)
{if(j!=0)
for( --j ; j!=0 ; --j)
free( (void*) pp[j] );
free((void*) pp[0]); free((void*) pp); return 0;
}
}
}
else { if(siz==m_m_m_) return 1;
else if(siz < m_m_m_) /* dovrebbe distruggere la
memoria eccessiva */
{ if(siz<=i_i_i_) return 1; /* la 1024ma volta che viene
chiamato free_m()*/
for(j=siz; j<m_m_m_; ++j) // v[0]...v[size]=size+1
free((void*) p_p_p_[j]);
pp=(vettore_array**) realloc(p_p_p_, (siz + 1) * sizeof
*pp );
if(pp==0) {printf("Fallimento realloc\n"); m_m_m_ =
siz; return 1;}
/* ritorna senza cambiare niente */
goto label;
}
pp= (vettore_array**) realloc( (void*) p_p_p_, (siz + 1) *
sizeof *pp);
if(pp==0) {printf("Fallimento realloc\n"); return 0;}
if( siz > i_i_i_)
{ for( j=i_i_i_; j<siz; ++j)
{pp[j]= (vettore_array*) malloc(
sizeof(vettore_array) );
if(pp[j]==0)
{if(j!=0)
for( --j ; j!=0 ; --j)
free( (void*) pp[j] );
free((void*) pp[0]); return 0;
}
}
}
}
label: ;
m_m_m_ = siz; p_p_p_=pp; return 1;
}
/* malloc_m: allocatore di memoria */
void* malloc_m(unsigned nbytes)
{Header *p, *prevp;
unsigned nunits, *k, *kk, led, size;
Header* morecore(unsigned);
unsigned verifica_all_m( void );
void stato_mem(void);
/*-------------------------------*/
if(libero_m_)
{
if(verifica_all_m()==0)
stato_mem();
}
if(i_i_i_>MEM_LIMIT || nbytes==0 ) return 0;
if(i_i_i_>=m_m_m_)
{if(mem_init( i_i_i_ + MAX_ARRAYS ) == 0) return 0;}
nunits = nbytes + sizeof(Header);
nunits = nunits/sizeof(Header) + (( nunits%sizeof(Header)
if((prevp=freep)==NULL) /* non esiste la free list */sizeof(unsigned) ) ? 1: 0) + 1;
{ base.s.ptr=freep=prevp=&base; base.s.size=0; }
for(p=prevp->s.ptr; ; prevp=p, p=p->s.ptr)
{if(p->s.size>=nunits) /* spazio insufficiente */
{if(p->s.size==nunits) /* esattamente */
{
prevp->s.ptr = p->s.ptr;
}
else /* alloca la parte finale */
{
p->s.size -= nunits;
p += p->s.size;
p->s.size =nunits;
}
freep = prevp;
/****************** Blocco aggiunto ************/
size = nbytes;
led = (size % sizeof(unsigned)!=0) ? 1: 0;
k = (unsigned*)(p+1); kk=k; --k;
p_p_p_[i_i_i_]->meno = *k;
p_p_p_[i_i_i_]->piu = kk[size/sizeof(unsigned)+ led];
p_p_p_[i_i_i_]->size = size;
p_p_p_[i_i_i_++]->p = (void*)(p+1);
/***********************************************/
return (void*) (p+1);
}
if(p==freep) /* la free list e' terminata */
{++yuyuy; /* numero delle volte di mem.
richieste al sistema */
if((p=morecore(nunits)) == NULL)
return NULL; /* non c'e' piu' spazio */
}
}
}
/* Ritorna il numero degli elementi;
se il numero degli elementi e' 0 ritorna (unsigned) -1
se errori ritorna 0 */
unsigned verifica_all_m( void )
{unsigned j, *k, *kk, xk, xkk, led;
/*----------------*/
if( p_p_p_==0 || i_i_i_==0 ) return -1;
for(j=0 ; j < i_i_i_ ; ++j)
{k = (unsigned*) (p_p_p_[j]->p); kk=k; --k;
led = (p_p_p_[j]->size % sizeof(unsigned)!=0) ? 1: 0;
if( (xk=kk[p_p_p_[j]->size/sizeof(unsigned) + led]) !=
(xkk=p_p_p_[j]->piu) )
{
/* nota bene: n:v significa NUOVO VALORE : VECCHIO VALORE */
sprintf(memo_ , "verifica_all_mMEM_+ p=%5p size=%5u p[-1]=%5u
p[max]=%5u n:v=%5u:%5u",
p_p_p_[j]->p, p_p_p_[j]->size, p_p_p_[j]->meno,
xkk, xk, xkk);
if(n_i_>2) name_[ n_i_ - 2 ]='+';
return 0;
}
if( (xk=*k) != (xkk=p_p_p_[j]->meno) )
{ sprintf(memo_ , "verifica_all_mMEM_- p=%5p size=%5u
p[-1]=%5u p[max]=%5u n:v=%5u:%5u",
p_p_p_[j]->p, p_p_p_[j]->size, xkk,
p_p_p_[j]->piu, xk, xkk);
if(n_i_>2) name_[n_i_ - 2]='-';
return 0;
}
}
return i_i_i_;
}
void verifica_all( void )
{if(verifica_all_m( )==0)
{printf("Errore nella memoria\n");
printf("memo=%s name=%s\n", memo_, name_ );
}
}
/* ritorna 0 se il vettore fa parte della lista
se pointer==0 ritorna 1 se tutto e' cancellato
2 se tutto e' cancellato tranne il puntatore iniziale
3 altrimenti
*/
unsigned verifica_m( void* pointer, unsigned *jj)
{unsigned j, *k, *kk, xk, xkk, led;
/*----------------*/
if(jj!=0) *jj=0;
if(pointer==0)
{if( i_i_i_==0 && p_p_p_==0 ) return 1;
else if(i_i_i_==0) return 2;
else return 3;
}
if(p_p_p_==0 ) return 1;
for(j=0 ; j < i_i_i_ ; ++j)
if( p_p_p_[j]->p == pointer ) break;
if(j==i_i_i_ ) {printf("verifica_mMEM_0 %p indice=%u memo=%s
name=%s\n", pointer, i_i_i_, memo_, name_ );
if(n_i_>2) name_[n_i_ -2]='0'; return 7;
}
k = (unsigned*) pointer; kk=k; --k;
led = (p_p_p_[j]->size % sizeof(unsigned)!=0) ? 1: 0;
*jj=j;
if( (xk=kk[p_p_p_[j]->size/sizeof(unsigned) + led]) !=
(xkk=p_p_p_[j]->piu) )
{ printf("p=%p size=%u p[-1]=%u p[max]=%u ", pointer,
p_p_p_[j]->size, *k, xk);
printf("verifica_mMEM_+ n:v>%u:%u\n", xk, xkk);
if(n_i_>2) name_[ n_i_ - 2 ]='+';
return 8;
}
if( (xk=*k) != (xkk=p_p_p_[j]->meno) )
{ printf("p=%p size=%u p[-1]=%u p[max]=%u ", pointer,
p_p_p_[j]->size, xkk, p_p_p_[j]->piu);
printf("verifica_mMEM_- n:v>%u:%u\n", xk, xkk);
if(n_i_>2) name_[n_i_ - 2]='-';
return 9;
}
else return 0;
}
unsigned verifica_p_m( void* pointer)
{unsigned jj;
return verifica_m( pointer, &jj);
}
static void free_list_m(void)
{while( list_i_ !=0 )
{--list_i_; free(list_[list_i_]);}
free(list_); list_=0; list_m_=0; freep=NULL;
}
static void free_vettore_m(void)
{if(p_p_p_==0) { m_m_m_=0; i_i_i_=0; return;}
while( i_i_i_ !=0 )
{--i_i_i_; free((void*) p_p_p_[i_i_i_]); }
free((void*) p_p_p_);
p_p_p_=0; m_m_m_=0;
}
static void inserisci(void* ap, unsigned jk, unsigned j)
{Header *bp, *p;
static unsigned f_cont=0;
/*-------------------*/
if(jk==0) ++f_cont;
bp = (Header*)ap - 1; /* punta all'header del blocco */
for( p=freep; !(bp>p && bp < p->s.ptr); p=p->s.ptr )
if( p >= p->s.ptr && (bp>p || bp < p->s.ptr) )
break; /* il blocco liberato e'
ad un estremo della lista*/
if(jk) goto label;
/********************************************/
if(j != i_i_i_ - 1)
{
p_p_p_[j]->p = p_p_p_[i_i_i_ - 1]->p;
p_p_p_[j]->size = p_p_p_[i_i_i_ - 1]->size;
p_p_p_[j]->meno = p_p_p_[i_i_i_ - 1]->meno;
p_p_p_[j]->piu = p_p_p_[i_i_i_ - 1]->piu;
}
p_p_p_[--i_i_i_]->p =0; p_p_p_[i_i_i_]->size=0;
p_p_p_[i_i_i_]->meno=0; p_p_p_[i_i_i_]->piu =0;
if(m_m_m_>1000 && f_cont%1024==0)
mem_init(i_i_i_+64);
/***********************************************/
label:
if(bp+bp->s.size == p->s.ptr)/*lo unisce al blocco dopo*/
{bp->s.size += p->s.ptr->s.size;
bp->s.ptr = p->s.ptr->s.ptr;
}
else bp->s.ptr=p->s.ptr;
if(p+p->s.size == bp)/* lo unisce al blocco prima*/
{p->s.size += bp->s.size;
p->s.ptr = bp->s.ptr;
}
else p->s.ptr=bp;
freep = p;
}
void free_all_m(void) {free_vettore_m(); free_list_m();}
/*Non usare free_all_m() ma free_a_i_m se ci sono oggetti
allocati da costruttori e distruttori del c++
(gli oggetti fuori da una qualsiasi procedura finiscono quando si
chiude
l'ultima istruzione del main) */
void free_a_i_m(void)
{if(i_i_i_==0)
{free_vettore_m(); free_list_m(); printf("MEMORIA DINAMICA
LIBERATA\n"); }
}
#define NALLOC 1024 /* numero minimo di unita' richieste */
/* morecore: chiede al sistema memoria aggiuntiva */
static Header* morecore(unsigned nu)
{char *cp, **p;
Header *up;
unsigned len;
/*-----------------------*/
if(nu<NALLOC) nu=NALLOC;
cp = (char*) malloc(nu * sizeof(Header));
if( cp==0 ) /* non c'e' piu' spazio */
return NULL;
if(list_i_ <= list_m_ )
{len = (list_m_==0 ? 128: 2*list_m_);
p = (char**) realloc(list_, len * sizeof *p);
if(p==0)
{free(cp); return 0;}
list_ = p;
list_m_ =len;
}
list_[list_i_++]=cp;
up=(Header*) cp;
up->s.size=nu;
inserisci((void*)(up+1), 1, 0);
return freep;
}
/* se pointer!=0 ritorna la size del pointer
ritorna 0 se il pointer non c'e' */
unsigned get_size_m( void* pointer )
{unsigned j;
/*----------------*/
if(pointer==0 || p_p_p_==0) return 0;
for(j=0 ; j < i_i_i_ ; ++j)
if( p_p_p_[j]->p == pointer ) break;
if(j==i_i_i_ ) return 0;
return p_p_p_[j]->size;
}
void init_w(const char *nam)
{unsigned i, j;
/*---------------------*/
if(nam==0) return;
if( n_i_ > 2 )
name_[n_i_ - 1]='|';
if( n_i_ >= 1016 ) // 0..14 carattere 15='|'
n_i_=0;
for(i=n_i_, j=0; j<15 && nam[j]!=0; ++i, ++j)
name_=nam[j];
for( ; j< 15; ++i, ++j)
name_=' ';
name_ = '#';
n_i_ += 16;
}
void leggi_mem(void)
{Header *u, *v;
unsigned j;
for( u = freep; u!=0 ; )
{printf("|v=%u s=%u|", (unsigned)u / sizeof(Header), u->s.size );
if(u->s.ptr==freep) break;
v=u->s.ptr;
if((u + u->s.size) != v)
{j = (UNS)(v-u) - u->s.size;
if(j<123456)
printf("%u", j );
else printf("#");
}
u=v;
}
}
void stato_mem(void)
{unsigned j;
leggi_mem();
fflush(stdout);
printf("\nRAPPORTO MEMORIA DINAMICA. ");
printf("Memoria richiesta al sistema=%u volte. ", yuyuy);
j=verifica_all_m();
if(j!=0 && j!=-1) printf("%u vettori allocati con successo\n", j);
else {if(j==0) goto label;
printf("Tutto bene. ");
j=verifica_m(0, 0);
if(j==1) printf("Sia la base sia il contatore sono NULLI\n");
else if(j==2) printf("Il contatore e' nullo ma la base no\n");
else {label: ;
printf("Errore nella memoria\n");
printf("memo=%s name=%s\n", memo_, name_ );
free_vettore_m(); free_list_m();
exit(0);
}
}
}
void controlla_m(char* st)
{printf("!%s!", st);
fflush(stdout);
if(verifica_all_m()==0)
{if(st) printf("ERRORE!");
fflush(stdout);
stato_mem();
}
}
/* free: inserisce in free list il blocco ap */
void free_m(void* ap)
{ unsigned j;
/*-------------------*/
if(ap==0) return ;
if(libero_m_)
{
if(verifica_all_m()==0)
stato_mem();
}
if(verifica_m(ap, &j))
{ printf("free_m(): "); stato_mem();
free_vettore_m(); free_list_m();
exit(0);
}
inserisci(ap, 0, j);
}
void stampa_chiamate(void){printf("memo=%s name=%s\n", memo_, name_
);}
#ifdef __cplusplus
}
#endif
// fine di extern C
/*************************CCCCCCC**********************************/
/* file.c che utilizza malloc_m()
c_compiler file.c mallocm.obj */
#include <stdio.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
void* malloc_m(unsigned nbytes);
unsigned verifica_all_m( void );
unsigned verifica_m( void* pointer, unsigned *jj);
unsigned verifica_p_m( void* pointer);
void free_m(void* ap);
void free_all_m(void);
void free_a_i_m(void);
unsigned get_size_m( void* pointer );
void stato_mem(void);
void leggi_mem(void);
void controlla_m(char* st);
void verifica_all( void );
void init_w(const char *nam);
void stampa_chiamate(void);
#ifdef __cplusplus
}
#endif
extern int libero_m_ ;
void g(void)
{char *r;
/**********************/
if(libero_m_) init_w("g() ");
r=malloc_m(100*sizeof(*r));
r[-1]='8'; /* errore per r[-1] */
/* errore non liberato r */
// free_m(r);
/* errore se non uso free_m(r) ed stato_mem() in main mi dice
"RAPPORTO MEMORIA DINAMICA. Memoria richiesta al sistema=1 volte.
1 vettori allocati con successo "
significa che mi sono dimenticato di cancellare un vettore
*/
}
void f(void)
{char *p;
int i;
/*********************/
if(libero_m_) init_w("f() ");
p=malloc_m(100*sizeof(*p));
for(i=0; i<110; ++i) p='0'; /* errore per i>=100 */
free_m(p); /* se libero_m_ = 1; identifica routine dell'errore */
/* se libero_m_ = 0; (default) identifica un errore */
g();
}
int main(void)
{// libero_m_ = 1; // scrive routines ove e' identificato l'errore
// se si identifica errore => "libero_m_ = 1;"
// nel codice normale ove non si identificano errori *non* si
// deve scrivere "libero_m_ = 1;"
if(libero_m_) init_w("main");
f();
stato_mem(); /* identifica eventuali errori e "momory leaks"*/
free_all_m(); /* si deve usare prima di uscire dal programma */
stato_mem(); /* se succede
"RAPPORTO MEMORIA DINAMICA. Memoria richiesta al sistema=1 volte.
Tutto bene. Sia
la base sia il contatore sono NULLI"
tutto sembra ok */
return 0;
}