Страницы

Translate

вторник, 24 декабря 2013 г.

Exercise 8.7. malloc accepts a size request without checking its plausibility; free believes that the block it is asked to free contains a valid size field. Improve these routines so they make more pains with error checking.

Exercise 8.7. malloc accepts a size request without checking its plausibility; free believes that the block it is asked to free contains a valid size field. Improve these routines so they  make more pains with error checking.






#include <stdio.h>
#include <stdlib.h>

#define MAXBYT 10240

typedef long Align; //for alignment to long boundary
union header
{
    struct  //block header
    {
        union header *ptr; //next block if on free list
        unsigned size;      //size of this block
    } s;
    Align x; //force alignment of blocks
};

typedef union header Header;

static Header base; //empty list to get started
static Header *freep = NULL; //start of free list
static Header *morecore(unsigned nu);
static Header *freeptr;
static Header *prevptr;
static unsigned maxalloc; //max bytes

/* malloc: universal storage allocator */
void *_malloc(unsigned nbytes)
{
    Header *p, *prevp;
    Header *moreroce(unsigned);
    unsigned nunits;
   
    if(nbytes > MAXBYT)
    {
        fprintf(stderr, "alloc: i can`t allocate more than %d bytes/n",
                    MAXBYT);
        return NULL;
    }   
    nunits = (nbytes + sizeof(Header) - 1)/sizeof(Header) + 1;
    if((prevp = freep) == NULL) //no free list yet
    {
        base.s.ptr = freeptr = prevptr = &base;
        base.s.size = 0;
    }
    for(p = prevp->s.ptr; ;prevp = p, p = p->s.ptr)
    {
        if(p->s.size >= nunits) //big enough
        {
            if(p->s.size == nunits) //exactly
                prevp->s.ptr = p->s.ptr;
            else //allocate tail end
            {
                p->s.size -= nunits;
                p += p->s.size;
                p->s.size = nunits;
            }
            freep = prevp;
            return (void *) (p+1);
        }
        if(p == freep) //wrapped around free list
            if((p = morecore(nunits)) == NULL)
                return NULL; // non left
    }
}

#define NALLOC 1024 //minimum units to request
/* morecore: ask system for more memory */
static Header *morecore(unsigned nu)
{
    char *cp, *sbrk(int);
    Header *up;
   
    if(nu < NALLOC)
        nu = NALLOC;
    cp = sbrk(nu * sizeof(Header));
    if(cp == (char *) -1) //no space at all
        return NULL;
    up = (Header *) cp;
    up->s.size = nu;
    maxalloc = (up->s.size > maxalloc) ? up->s.size : maxalloc;
    free((void *) (up + 1));
    return freep;
}

/* free: put block ap in free list */

void free(void *ap)
{
    Header *bp, *p;
   
    bp = (Header *) ap - 1; // point to block header
    if(bp->s.size == 0 || bp->s.size > maxalloc)
    {
        fprintf(stderr, "alloc: i can`t allocate more than %d bytes/n",
                    MAXBYT);
        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; //freed block at start or end of arena
    if(bp + bp->s.size == p->s.ptr) //join to upper nbr
    {
        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) //join to lower nbr
    {
        p->s.size += bp->s.size;
        p->s.ptr = bp->s.ptr;
    }
    else
        p->s.ptr = bp;
    freep = p;
}

Комментариев нет:

Отправить комментарий