内存分配与野指针

用一个闭环式链表管理内存分配。

1.头块是特殊块,下一个块指向自己本身,size = 0。

2.内存不足则向系统申请内存,并添加到链表中。


#include <stdio.h>

#include <unistd.h>



#define MIN_MALLOC 1024



union header {

    struct {

        union header *next;

        int size;

    } s;

    long Align;

};



typedef union header Header;



void *tmalloc(int);



void memorylink(Header *hp);



void *moremalloc(int nunit);



static Header root;    // 环形链表头

static Header *freep;  // 头指针



int main() {

    struct point {

        int x;

        char *s;

    };

    struct point *pt = (struct point *) tmalloc(10);

    pt->x = 10;

    pt->s = "mmm";

    printf("%s\n", pt->s);

    printf("------------------------\n");

    struct point *pt2 = (struct point *) tmalloc(20);

    pt->x = 10;

    pt->s = "pppppp";

    printf("%s\n", pt->s);

}



void *tmalloc(int nunit) {

    if (freep == NULL) {    // 第一次

        root.s.next = freep = &root;

        root.s.size = 0;

    }

    Header *p, *prevp;  // 链表当前位置

    p = prevp = NULL;   // 防止野指针

    for (p = freep;; prevp = p, p = p->s.next) {

        printf("该链上块大小:%d\n", p->s.size);

        if (p->s.size >= nunit) {

            if (p->s.size == nunit) {

                printf("刚刚好\n");

                prevp->s.next = p->s.next;

                return (void *) p;

            } else {

                printf("有多余\n");

                p->s.size -= nunit;

                return (void *) (p + p->s.size);

            }

        }



        if (prevp != NULL && p == freep) {   // 头位置闭环

            moremalloc(nunit);

        }

    }

}



void *moremalloc(int nunit) {

    printf("申请分配内存块:%d\n", nunit);

    if (nunit < MIN_MALLOC) {

        nunit = MIN_MALLOC;

    }

    void *cp = sbrk(nunit * sizeof(Header));

    if ((char *) cp == (char *) -1) {

        return NULL;    // error

    }

    Header *hp = (Header *) cp;

    hp->s.size = nunit;

    memorylink(hp);

}



void memorylink(Header *hp) {

    Header *prevp, *p;

    for (p = freep;; prevp = p, p = p->s.next) {

        if (prevp != NULL && p == freep) {

            break;  // 到达链表末端

        }

    }

    if (prevp + prevp->s.size == hp) {

        prevp->s.size += hp->s.size;

    } else {

        prevp->s.next = hp;

        hp->s.next = p;

    }

    printf("链接成功\n");

}


野指针:

1.指针变量没有被初始化。任何指针变量刚被创建时不能保证自动成为NULL指针,它的缺省值是随机的。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。

2.指针pfree或者delete之后,p指向的内存释放,但p没有置为NULL,所以if (p != NULL)达不到检测目的。


上面的

p = prevp = NULL;   // 防止野指针


如不显示赋值为NULL,则下面检查无效

if (prevp != NULL && p == freep) {   // 头位置闭环
moremalloc(nunit);
}

展开阅读全文