#include
#include
#define MAGIC (Header *)1111
typedef long Align;
union header {
struct {
union header *ptr;
unsigned size;
} s;
Align x;
};
typedef union header Header;
static Header base; /* Anfangs-Header */
static Header *freep = NULL; /* Einstiegspunkt in Free-Liste */
void* mymalloc(unsigned nbytes)
{
Header *p, *prevp;
static Header *morecore(unsigned);
unsigned nunits;
nunits = (nbytes+sizeof(Header)-1)/sizeof(Header) + 1;
if ((prevp = freep) == NULL) /* Erster Aufruf, Initialisierung */
{
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) /* Block gross genug */
{
if (p->s.size == nunits) /* Block passt genau */
prevp->s.ptr = p->s.ptr;
else
{
p->s.size -= nunits; /* Block wird geteilt */
p += p->s.size; /*Pointer auf abgeschnittenes Ende*/
p->s.size = nunits;
}
freep = prevp;
p->s.ptr=MAGIC; /* da *ptr nur in free gebraucht wird,
Magic zur Ueberpruefung von free */
return (void*) (p+1); /* zeigt auf Speicherblock,nicht *H */
}
if ( p == freep) /* p wieder beim Anfang,dh kein Platz*/
if ((p = morecore(nunits)) == NULL)
return NULL;
}
}
#define NALLOC 512 /* 512 * Header = 4 KB */
/* Eine static-Funktion ist ausserhalb ihres Files nicht sichtbar */
static Header *morecore(unsigned nu)
{
void *cp, *sbrk(int);
void myfree(void*);
Header *up;
if (nu < NALLOC)
nu = NALLOC;
cp = sbrk(nu * sizeof(Header));
if (cp == (char *) -1) /* sbrk liefert -1 im Fehlerfall */
return NULL;
up = (Header*) cp;
up->s.size = nu; /* Groesse wird eingetragen */
up->s.ptr = MAGIC; /* damit sich free nicht beschwert */
myfree((void*)(up+1)); /* Einbau in Free-Liste */
return freep;
}
void myfree(void *ap) /* Rueckgabe an Free-Liste */
{
Header *bp, *p;
bp = (Header*) ap - 1; /* Hier ist der Header des Blocks */
/* Die Liste wird durchmustert, der Block soll der
Adressgroesse nach richtig eingefuegt werden,
um Defragmentierung zu ermoeglichen. */
if (bp->s.ptr!=MAGIC) {
printf("bad magic number in pointer at %08lX %lu\n",ap,ap);
return ;
}
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; /* bp liegt vor Block mit kleinster oder hinter
Block mit groesster Adresse */
if (bp + bp->s.size == p->s.ptr)
{ /* Vereinigung mit oberem Nachbarn */
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 ) {
/* Vereinigung mit unterem Nachbarn */
p->s.size += bp->s.size;
p->s.ptr = bp->s.ptr;
} else
p->s.ptr = bp;
freep = p;
}
void* myrealloc(void *oldp,unsigned newsize)
{
void *newp ;
Header *h ;
unsigned oldsize ;
if (oldp==NULL)
return ( mymalloc(newsize) ) ;
h = (Header *)oldp - 1 ;
if (h->s.ptr!=MAGIC) {
printf("bad magic number in pointer at %08lX %lu\n",oldp,oldp);
return (NULL);
}
oldsize = h->s.size * sizeof(Header) - sizeof(Header) ; /* size in bytes */
printf("Pointer oldsize=0x%08lX %lu\n",oldsize,oldsize);
myfree(oldp);
newp = mymalloc(newsize);
if (newp==NULL)
return NULL ;
if (newp!=oldp)
memcpy(newp,oldp,(newsize < oldsize) ? newsize : oldsize ) ;
return (newp) ;
}
void* mycalloc(unsigned nelem,unsigned size)
{
void *p = mymalloc(nelem*size) ;
if (p) bzero(p,nelem*size) ;
return p ;
}
printfree()
{
Header *p ;
for (p=&base ; ; p=p->s.ptr)
{
printf("base=%08lX size=%5d\n",(char *)p,p->s.size*sizeof(Header));
if (p->s.ptr==&base) break ;
}
}
void bfree(void* p,unsigned int n) /* p-> Block ; n=sizeof block */
{
Header *bfreeheader ; /* header fuer block */
unsigned int units ;
if ( freep == NULL) /* Erster Aufruf, Initialisierung */
{
base.s.ptr = freep = &base;
base.s.size = 0;
}
units= (n-1)/sizeof(Header) + 1 ;
if (n % sizeof(Header) ) units-- ; /* falls blocksize % 8 nicht 0
sollen die letzten Bytes nicht
verwendet werden */
bfreeheader=(Header*)p;
bfreeheader->s.ptr = MAGIC ;
bfreeheader->s.size = units ;
myfree( (void *)(bfreeheader+1));
}
static int a[1024];
int* allocstatic()
{
if ( freep == NULL) /* Erster Aufruf, Initialisierung */
{
base.s.ptr = freep = &base;
base.s.size = 0;
}
return a;
}
int main()
{
char c;
int bool ;
unsigned n,b;
void *p ;
while (1){
bool=1;
printf("\n(m)alloc (c)alloc (f)ree (r)ealloc (s)tatic (b)free (q)uit : ");
fflush(stdin);
scanf("%c",&c);
fflush(stdin);
switch(c)
{
case 'm' : printf("Wieviel Bytes : ");
scanf("%d",&n);
p=mymalloc(n);
printf("Pointer zeigt auf Adresse 0x%08lX %lu\n",p,p);
break;
case 'c' : printf("Wieviel Elemente und Groesse der Elem. : ");
scanf("%d %d",&n,&b);
p=mycalloc(n,b);
printf("Pointer zeigt auf Adresse 0x%08lX %d\n",p,p);
break;
case 'f' : printf("Welche Addresse : ");
scanf("%d",&n);
p=(void *)n;
myfree(p);
break;
case 'r' : printf("Welche Addresse und wieviel Bytes : ");
scanf("%d %d",&n,&b);
p=(void *)n;
p=myrealloc(p,b);
printf("Pointer zeigt auf Address 0x%08lX %lu\n",p,p);
break;
case 's' : p=(void *)allocstatic();
printf("static Pointer zeigt auf 0x%08lX %lu\n",p,p);
break;
case 'b' : printf("Welche Addresse und wieviel Bytes : ");
scanf("%d %d",&n,&b);
p=(void *)n;
bfree(p,b);
break;
case 'q' :
printf("exit prg\n");
return(0) ;
default : bool=0;
break;
}
if (bool)
printfree();
}
}