C.Interface.And.Implementations—memory(复杂版本)的实现

1、After the call to  free,  p  holds a dangling pointer— a pointer that refers to memory that logically does not exist. Subse-quently dereferencing p  is an error, although if the block hasn’t been reallocated for another purpose, the error might go undetected. 

2、another error: deallocating free memory. 

3、Another error is deallocating memory that wasn’t allocated by malloc , calloc , or  realloc. 


针对以上错误,此版本memory实现较为复杂,使用了哈希表数据结构。


                  

    这个是内存的结构。整体而言用哈希表+链表进行存储。同时,释放的空间用freelist循环链表进行连接。有阴影的部分表示目前已经申请正在使用的空间。C函数中几个函数都是在这个数据结构上进行操作的。


==============================mem.h=====================================

#ifndef MEM_INCLUDED
#define MEM_INCLUDED
#include "except.h"

//exported exceptions
extern const Except_T Mem_Failed;

//exported functions
extern void *Mem_alloc(long nbytes,
                       const char *file, int line);
extern void *Mem_calloc(long count, long nbytes,
                       const char *file, int line);
extern void Mem_free(void *ptr,
                     const char *file, int line);
extern void *Mem_resize(void *ptr, long nbytes,
    const char *file, int line);
//exported macros
#define ALLOC(nbytes) \
    Mem_alloc((nbytes), __FILE__, __LINE__)
#define CALLOC(count, nbytes) \
    Mem_calloc((count), (nbytes), __FILE__, __LINE__)
#define NEW(p) ((p) = ALLOC((long)sizeof *(p)))
#define NEW0(p) ((p) = CALLOC(1, (long)sizeof *(p)))
#define FREE(ptr) ((void)(Mem_free((ptr),\
    __FILE__, __LINE__), (ptr) = 0))
#define RESIZE(ptr, nbytes)((ptr) = Mem_resize((ptr),\
    (nbytes), __FILE__, __LINE__))
#endif

=============================memchk.c==================================

#include <stdlib.h>
#include <string.h>
#include "assert.h"
#include "except.h"
#include "mem.h"

//checking types
union align{
    int i;
    long l;
    long *lp;
    void *p;
    void (*fp)(void);
    float f;
    double d;
    long double ld;
};

//checking macros
#define hash(p, t) (((unsigned long)(p)>>3) & \
    (sizeof (t)/sizeof((t)[0])-1))
#define NDESCRIPTORS 512
#define NALLOC((4096 + sizeof(union align)-1)/ \
    (sizeof(union align)))*(sizeof (union align))

//data
const Except_T Mem_Failed = { "Allocation Failed" };

//checking data
static struct descriptor{
    struct descriptor *free;
    struct descriptor *link;
    const void *ptr;
    long size;
    const char *file;
    int line;
} *htab[2048];
static struct descriptor freelist = { &freelist };

//checking functions
static struct descriptor *find(const void *ptr){
    struct descriptor *bp = htab[hash(ptr, htab)];

    while(bp && bp->ptr != ptr)
        bp = bp->link;

    return bp;
}

void Mem_free(void *ptr, const char *file, int line){
    if(ptr){
        struct descriptor *bp;
        if(((unsigned long)ptr)%(sizeof (union align)) != 0
            || (bp = find(ptr)) == NULL || bp->free)
            Except_raise(&Assert_Failed, file, line);
        bp->free = freelist.free;
        freelist.free = bp;
    }
}

void *Mem_resize(void *ptr, long nbytes,
                 const char *file, int line){
    struct descriptor *bp;
    void *newptr;

    assert(ptr);
    assert(nbytes > 0);
    if(((unsigned long)ptr)%(sizeof (union align)) != 0
        || (bp = find(ptr)) == NULL || bp->free)
        Except_raise(&Assert_Failed, file, line);
    newptr = Mem_alloc(nbytes, file, line);
    memcpy(newptr, ptr, 
        nbytes < bp->size ? nbytes : bp->size);
    Mem_free(ptr, file, line);
    return newptr;
}

void *Mem_calloc(long count, long nbytes,
                 const char *file, int line){
    void *ptr;

    assert(count > 0);
    assert(nbytes > 0);
    ptr = Mem_alloc(count*nbytes, file, line);
    memset(ptr, '\0', count*nbytes);
    return ptr;
}

static struct descriptor *dalloc(void *ptr, long size, 
    const char *file, int line){
    static struct descriptor *avail;
    static int nleft;

    if(nleft <= 0){
        avail = malloc(NDESCRIPTORS * sizeof (*avail));
        if(avail == NULL)
            return NULL;
        nleft = NDESCRIPTORS;
    }

    avail->ptr = ptr;
    avail->size = size;
    avail->file = file;
    avail->line = line;
    avail->free = avail->link = NULL;
    nleft--;
    return avail++;
}

void *Mem_alloc(long nbytes, const char *file, int line){
    struct descriptor *bp;
    void *ptr;
    
    assert(nbytes > 0);
    //round nbytes up to an alignment boundary>
    nbytes = ((nbytes + sizeof(union align) - 1)/
        (sizeof(union align)))*(sizeof(union align));
    for(bp = freelist.free; bp; bp = bp->free){
        if(bp->size > nbytes){
            //use the end of the block at bp->ptr
            bp->size -= nbytes;
            ptr = (char*)bp->ptr + bp->size;
            if((bp = dalloc(ptr, nbytes, file, line)) != NULL){
                unsigned h = hash(ptr, htab);
                bp->link = htab[h];
                htab[h] = bp;
                return ptr;
            }else{
                if(file == NULL)
                    RAISE(Mem_Failed);
                else
                    Except_raise(&Mem_Failed, file, line);
            }
        }
        if(bp == &freelist){
            struct descriptor *newptr;
            //<newptr <- a block of size NALLOC + nbytes >
            if((ptr = malloc(nbytes + NALLOC)) == NULL
                || (newptr = dalloc(ptr, nbytes+NALLOC,
                __FILE__, __LINE__)) == NULL)
            {
                if(file == NULL)
                    RAISE(Mem_Failed);
                else
                    Except_raise(&Mem_Failed, file, line);
            }
            newptr->free = freelist.free;
            freelist.free = newptr;
        }
    }

    assert(0);
    return NULL;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值