首页 > 解决方案 > CS:APP Malloc Lab - 为什么我的代码应该只执行一次却重复了 12 次?

问题描述

我是一名使用在线资料独自学习 CS:APP3e(计算机系统:程序员视角)的学生。我在 Malloc Lab 工作,遇到了无法调试的问题。我编写了自己的显式空闲列表分配器,它适用于诸如short1、short2、coalescing 之类的简单跟踪。但是,它会在诸如binary2.rep之类的较长跟踪上出现段错误。

该设计遵循 CS:APP 教科书的铭文:双字对齐,每个块最少 3 个双字(=24 字节),空闲块的“pred”和“succ”指针。我按 LIFO 顺序维护列表。

使用我自己的跟踪,我发现它何时在binary2.rep上出现段错误。跟踪文件如下所示:

1024100       /* Unused number */
12000         /* Number of IDs */
16000         /* Number of operations */
1             /* Unused number */
a 0 16        /* allocate 16 bytes. Job ID = 0 */
a 1 112       /* allocate 112 bytes. Job ID = 1 */
a 2 16
a 3 112
a 4 16
a 5 112
(...)

它旨在交替调用 malloc(16) 和 malloc(112)。在第 694 次调用之前,我的显式空闲列表分配器执行没有错误。从第 695 次调用开始,我的代码开始生成错误消息“损坏的大小与 prev_size”。从 800-something 调用中,我的代码段错误而没有产生任何错误消息。

为了弄清楚发生了什么,我添加了一个全局变量

int cnt = 0;

每次调用 mm_malloc() 时都会增加它,并打印它。我发现:mm_malloc() 被调用了 12 倍。

我期待以下日志:

extend_heap:
Heap (0xf6153018):
0xf6153018: header: [8:a] footer: [8:a]
0xf6153020: header: [4096:f]     pred: [(nil)]     succ: [(nil)]     footer: [4096:f]
0xf6154020: EOL
CNT: 1
place:
Heap (0xf6153018):
0xf6153018: header: [8:a] footer: [8:a]
0xf6153020: header: [24:a] footer: [24:a]
0xf6153038: header: [4072:f]     pred: [(nil)]     succ: [(nil)]     footer: [4072:f]
0xf6154020: EOL
mm_malloc:
Heap (0xf6153018):
0xf6153018: header: [8:a] footer: [8:a]
0xf6153020: header: [24:a] footer: [24:a]
0xf6153038: header: [4072:f]     pred: [(nil)]     succ: [(nil)]     footer: [4072:f]
0xf6154020: EOL
extend_heap:
Heap (0xf6153018):
0xf6153018: header: [8:a] footer: [8:a]
0xf6153020: header: [4096:f]     pred: [(nil)]     succ: [(nil)]     footer: [4096:f]
0xf6154020: EOL

但是得到了以下结果:

extend_heap:
Heap (0xf6153018):
0xf6153018: header: [8:a] footer: [8:a]
0xf6153020: header: [4096:f]     pred: [(nil)]     succ: [(nil)]     footer: [4096:f]
0xf6154020: EOL
CNT: 1
place:
Heap (0xf6153018):
0xf6153018: header: [8:a] footer: [8:a]
0xf6153020: header: [24:a] footer: [24:a]
0xf6153038: header: [4072:f]     pred: [(nil)]     succ: [(nil)]     footer: [4072:f]
0xf6154020: EOL
mm_malloc:
Heap (0xf6153018):
0xf6153018: header: [8:a] footer: [8:a]
0xf6153020: header: [24:a] footer: [24:a]
0xf6153038: header: [4072:f]     pred: [(nil)]     succ: [(nil)]     footer: [4072:f]
0xf6154020: EOL
extend_heap:
Heap (0xf6153018):
0xf6153018: header: [8:a] footer: [8:a]
0xf6153020: header: [4096:f]     pred: [(nil)]     succ: [(nil)]     footer: [4096:f]
0xf6154020: EOL
CNT: 2
place:
Heap (0xf6153018):
0xf6153018: header: [8:a] footer: [8:a]
0xf6153020: header: [24:a] footer: [24:a]
0xf6153038: header: [4072:f]     pred: [(nil)]     succ: [(nil)]     footer: [4072:f]
0xf6154020: EOL
mm_malloc:
Heap (0xf6153018):
0xf6153018: header: [8:a] footer: [8:a]
0xf6153020: header: [24:a] footer: [24:a]
0xf6153038: header: [4072:f]     pred: [(nil)]     succ: [(nil)]     footer: [4072:f]
0xf6154020: EOL
extend_heap:
Heap (0xf6153018):
0xf6153018: header: [8:a] footer: [8:a]
0xf6153020: header: [4096:f]     pred: [(nil)]     succ: [(nil)]     footer: [4096:f]
0xf6154020: EOL
CNT: 3
place:
Heap (0xf6153018):
0xf6153018: header: [8:a] footer: [8:a]
0xf6153020: header: [24:a] footer: [24:a]
0xf6153038: header: [4072:f]     pred: [(nil)]     succ: [(nil)]     footer: [4072:f]
0xf6154020: EOL
mm_malloc:
Heap (0xf6153018):
0xf6153018: header: [8:a] footer: [8:a]
0xf6153020: header: [24:a] footer: [24:a]
0xf6153038: header: [4072:f]     pred: [(nil)]     succ: [(nil)]     footer: [4072:f]
0xf6154020: EOL
extend_heap:
Heap (0xf6153018):
0xf6153018: header: [8:a] footer: [8:a]
0xf6153020: header: [4096:f]     pred: [(nil)]     succ: [(nil)]     footer: [4096:f]
0xf6154020: EOL
(...)
CNT: 12
place:
Heap (0xf6153018):
0xf6153018: header: [8:a] footer: [8:a]
0xf6153020: header: [24:a] footer: [24:a]
0xf6153038: header: [4072:f]     pred: [(nil)]     succ: [(nil)]     footer: [4072:f]
0xf6154020: EOL
mm_malloc:
Heap (0xf6153018):
0xf6153018: header: [8:a] footer: [8:a]
0xf6153020: header: [24:a] footer: [24:a]
0xf6153038: header: [4072:f]     pred: [(nil)]     succ: [(nil)]     footer: [4072:f]
0xf6154020: EOL

这是我的源代码(mm.c)的样子:

/* 
 * Simple, 32-bit and 64-bit clean allocator based on explicit free
 * lists, first-fit placement, and boundary tag coalescing, as described
 * in the CS:APP3e text. Blocks must be aligned to doubleword (8 byte) 
 * boundaries. Minimum block size is 16 bytes. Insertion policy is LIFO. 
 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "mm.h"
#include "memlib.h"

team_t team = {
    "A",
    "B",
    "C",
    "",
    ""
};

/* Macros for heapchecker */
#define DEBUG
#define CHECKHEAP    printf("%s%c\n", __func__, ':'); checkheap(1);


/* $begin mallocmacros */
/* Basic constants and macros */
#define WSIZE       4       /* Word and header/footer size (bytes) */ //line:vm:mm:beginconst
#define DSIZE       8       /* Double word size (bytes) */
#define CHUNKSIZE  (1<<12)  /* Extend heap by this amount (bytes) */  //line:vm:mm:endconst 

#define MAX(x, y) ((x) > (y)? (x) : (y))  

/* Pack a size and allocated bit into a word */
#define PACK(size, alloc)  ((size) | (alloc)) //line:vm:mm:pack

/* Read and write a word at address p */
#define GET(p)       (*(unsigned int *)(p))            //line:vm:mm:get
#define PUT(p, val)  (*(unsigned int *)(p) = (val))    //line:vm:mm:put

/* Read the size and allocated fields from address p */
#define GET_SIZE(p)  (GET(p) & ~0x7)                   //line:vm:mm:getsize
#define GET_ALLOC(p) (GET(p) & 0x1)                    //line:vm:mm:getalloc

/* Given block ptr bp, compute address of its header and footer */
#define HDRP(bp)       ((char *)(bp) - WSIZE)                      //line:vm:mm:hdrp
#define FTRP(bp)       ((char *)(bp) + GET_SIZE(HDRP(bp)) - DSIZE) //line:vm:mm:ftrp

/* Given block ptr bp, compute address of next and previous blocks */
#define NEXT_BLKP(bp)  ((char *)(bp) + GET_SIZE(((char *)(bp) - WSIZE))) //line:vm:mm:nextblkp
#define PREV_BLKP(bp)  ((char *)(bp) - GET_SIZE(((char *)(bp) - DSIZE))) //line:vm:mm:prevblkp

/* Given block ptr bp, return next square's address */
#define NEXT_SQR(bp)    ((char*)(bp) + WSIZE)


#define MIN_BLOCK_SIZE  3*DSIZE

/* $end mallocmacros */

/* Global variables */
static char *heap_listp = 0;  /* Pointer to first block */  
static char *free_ptr = 0; /* Pointer to last accessed(LIFO) empty block */
int cnt = 0;

/* Function prototypes for internal helper routines */
static void *extend_heap(size_t words);
static void place(void *bp, size_t asize);
static void *find_fit(size_t asize);
static void *coalesce(void *bp);
static void printblock(void *bp); 
static void checkheap(int verbose);
static void checkblock(void *bp);

/* 
 * mm_init - Initialize the memory manager 
 */
/* $begin mminit */
int mm_init(void) 
{
    mem_deinit();
    mem_init();
    heap_listp = NULL;
    free_ptr = NULL;
    
    /* Create the initial empty heap */
    if ((heap_listp = mem_sbrk(4*WSIZE)) == (void *)-1) //line:vm:mm:begininit
        return -1;
    PUT(heap_listp, 0);                          /* Alignment padding */
    PUT(heap_listp + (1*WSIZE), PACK(DSIZE, 1)); /* Prologue header */ 
    PUT(heap_listp + (2*WSIZE), PACK(DSIZE, 1)); /* Prologue footer */ 
    PUT(heap_listp + (3*WSIZE), PACK(0, 1));     /* Epilogue header */
    heap_listp += (2*WSIZE);                     //line:vm:mm:endinit  

    /* Extend the empty heap with a free block of CHUNKSIZE bytes */
    if (extend_heap(CHUNKSIZE/WSIZE) == NULL) {
        return -1;
    }
    return 0;
}
/* $end mminit */

/* 
 * mm_malloc - Allocate a block with at least size bytes of payload 
 */
/* $begin mmmalloc */
void *mm_malloc(size_t size) 
{
    #ifdef DEBUG
        cnt++;
        printf("CNT: %d\n", cnt);
    #endif
    size_t asize;      /* Adjusted block size */
    size_t extendsize; /* Amount to extend heap if no fit */
    char *bp;      

    if (heap_listp == NULL){
        mm_init();
    }
    
    /* Ignore spurious requests */
    if (size == 0)
        return NULL;

    /* Adjust block size to include overhead and alignment reqs. */
    if (size <= MIN_BLOCK_SIZE - DSIZE)                       
        asize = MIN_BLOCK_SIZE;                                
    else
        asize = DSIZE * ( (size + (MIN_BLOCK_SIZE - DSIZE) + (DSIZE-1)) / DSIZE); 

    /* Search the free list for a fit */
    if ((bp = find_fit(asize)) != NULL) { 
        place(bp, asize);                 
        #ifdef DEBUG
            CHECKHEAP
        #endif
        return bp;
    }

    /* No fit found. Get more memory and place the block */
    extendsize = MAX(asize,CHUNKSIZE);               
    if ((bp = extend_heap(extendsize/WSIZE)) == NULL)  
        return NULL;                                  
    place(bp, asize);                                 
    #ifdef DEBUG
        CHECKHEAP
    #endif
    return bp;
} 
/* $end mmmalloc */

/* 
 * mm_free - Free a block 
 */
/* $begin mmfree */
void mm_free(void *bp)
{
    if (bp == 0) 
        return;

    size_t size = GET_SIZE(HDRP(bp));
    if (heap_listp == 0){
        mm_init();
    }

    PUT(HDRP(bp), PACK(size, 0));
    PUT(FTRP(bp), PACK(size, 0));
    
    PUT(bp, NULL);  /* ‘pred’ pointer of this block is NULL pointer */
    PUT(NEXT_SQR(bp), free_ptr); /* ‘succ’ pointer of this block is previous ‘top’ of stack */
    if(free_ptr != NULL)
        PUT(free_ptr, bp); /* ‘prev’ pointer of previous ‘top’ of stack is this new bp. */
    free_ptr = bp;
    
    coalesce(bp);

    #ifdef DEBUG
        CHECKHEAP
    #endif
}

/*
 * coalesce - Boundary tag coalescing. Return ptr to coalesced block
 */
static void *coalesce(void *bp) 
{
    /* We assume that coalesce(bp) has been called following extend_heap or mm_free.
     * Therefore, the block pointed to by bp is also pointed to by free_ptr; it is the top of stack.
     * In Cases 2-4, there is another allocated block besides bp(top). This means that bp's succ pointer would
     * not be NULL, other blocks' pred pointers would not be NULL. Of course, bp's pred pointer would be NULL,
     * and we cannot guarantee any conditions about other blocks' succ pointers.
     */
    size_t prev_alloc = GET_ALLOC(FTRP(PREV_BLKP(bp)));
    size_t next_alloc = GET_ALLOC(HDRP(NEXT_BLKP(bp)));
    size_t size = GET_SIZE(HDRP(bp));

    if (prev_alloc && next_alloc) {            /* Case 1 */
        return bp;
    }

    else if (prev_alloc && !next_alloc) {      /* Case 2 */
        void* a = bp;
        void* a1 = GET(a);  void* a2 = GET(NEXT_SQR(a));    /* The 'this' block, and its pointers */
        void* b = NEXT_BLKP(bp);
        void* b1 = GET(b);  void* b2 = GET(NEXT_SQR(b));    /* The next block, and its pointers */
        
        /* a1 is NULL, a2 is not NULL, b1 is not NULL, b2 may or may not be NULL */
        
        if(b == a2) { /* b, the next block, is 2nd top */
            /* Unified block */
            size += GET_SIZE(HDRP(NEXT_BLKP(bp)));
            PUT(HDRP(bp), PACK(size, 0));
            PUT(FTRP(bp), PACK(size, 0));
            PUT(bp, NULL);          /* Pred pointer of top */
            PUT(NEXT_SQR(bp), b2);  /* Succ pointer of top */
            
            /* Block at b2, if it exists */
            if(b2 != NULL) {
                PUT(b2, free_ptr);
            }
        }
        else {
            size += GET_SIZE(HDRP(NEXT_BLKP(bp)));
            PUT(HDRP(bp), PACK(size, 0));
            PUT(FTRP(bp), PACK(size, 0));
            PUT(bp, NULL);          /* Pred pointer of top */
            PUT(NEXT_SQR(bp), a2);  /* Succ pointer of top */
            
            /* Block at a2 */
            PUT(a2, free_ptr);
            /* Block at b1 */
            PUT(NEXT_SQR(b1), b2);
            /* Block at b2, if it exists */
            if(b2 != NULL) {
                PUT(b2, b1);
            }
        }
    }

    else if (!prev_alloc && next_alloc) {      /* Case 3 */
        void* a = PREV_BLKP(bp);
        void* a1 = GET(a);  void* a2 = GET(NEXT_SQR(a));    /* The previous block, and its pointers */
        void* b = bp;
        void* b1 = GET(b);  void* b2 = GET(NEXT_SQR(b));    /* The 'this' block, and its pointers */
        
        /* b1 is NULL, b2 is not NULL, a1 is not NULL, a2 may or may not be NULL */
        
        if(a == b2) { /* a, the previous block, is 2nd top */
            /* Unified block */
            size += GET_SIZE(HDRP(PREV_BLKP(bp)));
            PUT(FTRP(bp), PACK(size, 0));
            PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
            bp = PREV_BLKP(bp);
            free_ptr = bp;          /* Re-establish top of stack */
            PUT(bp, NULL);          /* Pred pointer of top */
            PUT(NEXT_SQR(bp), a2);  /* Succ pointer of top */
            
            /* Block at a2, if it exists */
            if(a2 != NULL) {
                PUT(a2, free_ptr);
            }
        }
        else {
            /* Unified block */
            size += GET_SIZE(HDRP(PREV_BLKP(bp)));
            PUT(FTRP(bp), PACK(size, 0));
            PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
            bp = PREV_BLKP(bp);
            free_ptr = bp;          /* Re-establish top of stack */
            PUT(bp, NULL);          /* Pred pointer of top */
            PUT(NEXT_SQR(bp), b2);  /* Succ pointer of top */
            
            /* Block at b2 */
            PUT(b2, free_ptr);
            /* Block at a1 */
            PUT(NEXT_SQR(a1), a2);
            /* Block at a2, if it exists */
            if(a2 != NULL) {
                PUT(a2, a1);
            }
        }
    }

    else {                                      /* Case 4 */
        void* a = PREV_BLKP(bp);
        void* a1 = GET(a);  void* a2 = GET(NEXT_SQR(a));    /* The previous block, and its pointers */
        void* b = bp;
        void* b1 = GET(b);  void* b2 = GET(NEXT_SQR(b));    /* The 'this' block, and its pointers */
        void* c = NEXT_BLKP(bp);
        void* c1 = GET(b);  void* c2 = GET(NEXT_SQR(c));    /* The next block, and its pointers */
        
        /* a1 is not NULL, a2 may or may not be NULL,
         * b1 is NULL, b2 is not NULL,
         * c1 is not NULL, c2 may or may not be NULL */
        
        if(b2 == a) {           /* a is second top */
            if(a2 == c) {       /* c is third top */
                /* Unified block */
                size += GET_SIZE(HDRP(PREV_BLKP(bp))) + GET_SIZE(FTRP(NEXT_BLKP(bp)));
                PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
                PUT(FTRP(NEXT_BLKP(bp)), PACK(size, 0));
                bp = PREV_BLKP(bp);
                free_ptr = bp;          /* Re-establish top of stack */
                PUT(bp, NULL);          /* Pred pointer of top */
                PUT(NEXT_SQR(bp), c2);  /* Succ pointer of top */

                /* Block at b2(=a), a1(=b), a2(=c), c1(=a) are all unified block */
                /* Block at c2, if it exists */
                if(c2 != NULL) {
                    PUT(c2, free_ptr);
                }
            }
            else {
                /* Unified block */
                size += GET_SIZE(HDRP(PREV_BLKP(bp))) + GET_SIZE(FTRP(NEXT_BLKP(bp)));
                PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
                PUT(FTRP(NEXT_BLKP(bp)), PACK(size, 0));
                bp = PREV_BLKP(bp);
                free_ptr = bp;          /* Re-establish top of stack */
                PUT(bp, NULL);          /* Pred pointer of top */
                PUT(NEXT_SQR(bp), a2);  /* Succ pointer of top */
                
                /* Block at b2(=a), a1(=b) are unified block */
                /* Block at a2. It exists */
                PUT(a2, free_ptr);
                /* Block at c1. It exists */
                PUT(NEXT_SQR(c1), c2);
                /* Block at c2, if it exists */
                if(c2 != NULL) {
                    PUT(c2, c1);
                }
            }
        }
        else if (b2 == c) {     /* c is second top */
            if(c2 == a) {       /* a is third top */
                /* Unified block */
                size += GET_SIZE(HDRP(PREV_BLKP(bp))) + GET_SIZE(FTRP(NEXT_BLKP(bp)));
                PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
                PUT(FTRP(NEXT_BLKP(bp)), PACK(size, 0));
                bp = PREV_BLKP(bp);
                free_ptr = bp;          /* Re-establish top of stack */
                PUT(bp, NULL);          /* Pred pointer of top */
                PUT(NEXT_SQR(bp), a2);  /* Succ pointer of top */
                
                /* Block at b2(=c), c1(=b), c2(=a), a1(=c) are all unified block */
                /* Block at a2, if it exists */
                if(a2 != NULL) {
                    PUT(a2, free_ptr);
                }
            }
            else {
                /* Unified block */
                size += GET_SIZE(HDRP(PREV_BLKP(bp))) + GET_SIZE(FTRP(NEXT_BLKP(bp)));
                PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
                PUT(FTRP(NEXT_BLKP(bp)), PACK(size, 0));
                bp = PREV_BLKP(bp);
                free_ptr = bp;          /* Re-establish top of stack */
                PUT(bp, NULL);          /* Pred pointer of top */
                PUT(NEXT_SQR(bp), c2);  /* Succ pointer of top */
                
                /* Block at b2, c1 are unified block */
                /* Block at c2. It exists */
                PUT(c2, free_ptr);
                /* Block at a1. It exists */
                PUT(NEXT_SQR(a1), a2);
                /* Block at a2, if it exists */
                if(a2 != NULL) {
                    PUT(a2, a1);
                }
            }
        }
        else {
            /* Unified block */
                size += GET_SIZE(HDRP(PREV_BLKP(bp))) + GET_SIZE(FTRP(NEXT_BLKP(bp)));
                PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
                PUT(FTRP(NEXT_BLKP(bp)), PACK(size, 0));
                bp = PREV_BLKP(bp);
                free_ptr = bp;          /* Re-establish top of stack */
                PUT(bp, NULL);          /* Pred pointer of top */
                PUT(NEXT_SQR(bp), b2);  /* Succ pointer of top */
            if(a2 == c) {
                /* Block at a2(=c), c1(=a) are unified block */
                /* Block at b2 */
                PUT(b2, free_ptr);
                /* Block at c2, If it exists */
                if(c2 != NULL) {
                    PUT(c2, a1);
                }
                /* Block at a1 */
                PUT(NEXT_SQR(a1), c2);
            }
            else if(c2 == a) {
                /* Block at c2(=a), a1(=c) are unified block */
                /* Block at b2 */
                PUT(b2, free_ptr);
                /* Block at c1 */
                PUT(NEXT_SQR(c1), a2);
                /* Block at a2, If it exists */
                if(a2 != NULL) {
                    PUT(a2, c1);
                }
            }
            else {
                /* Block at b2 */
                PUT(b2, free_ptr);
                /* Block at a1 */
                PUT(NEXT_SQR(a1), a2);
                /* Block at a2, if it exists */
                if(a2 != NULL) {
                    PUT(a2, a1);
                }
                /* Block at c1 */
                PUT(NEXT_SQR(c1), c2);
                /* Block at c2, if it exists */
                if(c2 != NULL) {
                    PUT(c2, c1);
                }
            }
        }
    }
    
    #ifdef DEBUGG
        CHECKHEAP
    #endif
    
    return bp;
}
/* $end mmfree */

/*
 * mm_realloc
 * This function is never called for trace files I used.
 */
void *mm_realloc(void *ptr, size_t size)
{
    return NULL;
}

/* 
 * mm_checkheap - Check the heap for correctness
 */
void mm_checkheap(int verbose)  
{ 
    checkheap(verbose);
}

/* 
 * The remaining routines are internal helper routines 
 */

/* 
 * extend_heap - Extend heap with free block and return its block pointer
 */
/* $begin mmextendheap */
static void *extend_heap(size_t words) 
{
    char *bp;
    size_t size;

    /* Allocate an even number of words to maintain alignment */
    size = (words % 2) ? (words+1) * WSIZE : words * WSIZE; //line:vm:mm:beginextend
    if ((long)(bp = mem_sbrk(size)) == -1)  
        return NULL;                                        //line:vm:mm:endextend

    /* Initialize free block header/footer and the epilogue header */
    PUT(HDRP(bp), PACK(size, 0));         /* Free block header */   //line:vm:mm:freeblockhdr
    PUT(FTRP(bp), PACK(size, 0));         /* Free block footer */   //line:vm:mm:freeblockftr
    PUT(HDRP(NEXT_BLKP(bp)), PACK(0, 1)); /* New epilogue header */ //line:vm:mm:newepihdr

    
    PUT(bp, NULL);  /* ‘pred’ pointer of this block is NULL pointer */
    PUT(NEXT_SQR(bp), free_ptr); /* ‘succ’ pointer of this block is previous ‘top’ of stack */
    if(free_ptr != NULL)
        PUT(free_ptr, bp); /* ‘prev’ pointer of previous ‘top’ of stack is this new bp. */
    free_ptr = bp;
    
    /* Coalesce if the previous block was free */
    void* p = coalesce(bp);
    #ifdef DEBUG
        CHECKHEAP
    #endif
    return p;                                          //line:vm:mm:returnblock
}
/* $end mmextendheap */

/* 
 * place - Place block of asize bytes at start of free block bp 
 *         and split if remainder would be at least minimum block size
 */
static void place(void *bp, size_t asize)
{
    size_t csize = GET_SIZE(HDRP(bp));

    int use_all_space = ( (csize - asize) < (MIN_BLOCK_SIZE) );
      /* 0 if it splits and makes small free block, 1 if it uses all space */

    int write_to_top = ( bp == free_ptr );
     /* 0 if we’re not writing to top, 1 if we are */
    
    //printf("%d\t %d\n", use_all_space, write_to_top);

    char* alpha = NULL;
    char* gamma = NULL;

    if( use_all_space && write_to_top) /* Case 1 */ {
       alpha = GET(NEXT_SQR(bp));       /* Pointer to next free block in “Stack” */
        if(alpha != NULL)
            PUT(alpha, NULL);           /* Change pred of alpha to “NULL” */
       free_ptr = alpha;                /* Change top of “Stack” */

       /* Allocate space */
       PUT(HDRP(bp), PACK(csize, 1));
       PUT(FTRP(bp), PACK(csize, 1));
    }
    else if (!use_all_space && write_to_top) /* Case 2 */ {
       /* Get pointer to next free block within LIFO stack */
      alpha = GET(NEXT_SQR(bp));

       /* Allocate space */
      PUT(HDRP(bp), PACK(asize, 1));
      PUT(FTRP(bp), PACK(asize, 1));
      bp = NEXT_BLKP(bp);
      PUT(HDRP(bp), PACK(csize - asize, 0));
      PUT(FTRP(bp), PACK(csize - asize, 0));    /* bp now points to ‘new free block’ */
    
      //printf("Pointer addresses: %p %p %p\n", bp, NEXT_SQR(bp), alpha);

      PUT(bp, NULL);                /* Make pred of bp “NULL” */
      PUT(NEXT_SQR(bp), alpha);     /* Make succ of bp “alpha” */
      if(alpha != NULL)
        PUT(alpha, bp);             /* Change pred of alpha to “bp” */
      free_ptr = bp;                /* Change top of “Stack” */
    }
    else if( use_all_space && !write_to_top) /* Case 3 */ {
        /* Get pointer to previous free block within LIFO stack */
        gamma = GET(bp);
        /* Get pointer to next free block within LIFO stack */
        alpha = GET(NEXT_SQR(bp));
        
        if(gamma != NULL)
            PUT(NEXT_SQR(gamma), alpha);    /* Change succ of gamma to “alpha” */
        if(alpha != NULL)
            PUT(alpha, gamma);          /* Change pred of alpha to “gamma” */

        /* Allocate space */
        PUT(HDRP(bp), PACK(csize, 1));
        PUT(FTRP(bp), PACK(csize, 1));
    }
    else /* Case 4 */ {

        /* Get pointer to previous free block within LIFO stack */
        gamma = GET(bp);
        /* Get pointer to next free block within LIFO stack */
        alpha = GET(NEXT_SQR(bp));

        /* Allocate space */
        PUT(HDRP(bp), PACK(asize, 1));
        PUT(FTRP(bp), PACK(asize, 1));
        bp = NEXT_BLKP(bp);
        PUT(HDRP(bp), PACK(csize - asize, 0));
        PUT(FTRP(bp), PACK(csize - asize, 0));  /* bp now points to ‘new free block’ */


        PUT(bp, NULL);                      /* Make pred of bp “NULL” */
        PUT(NEXT_SQR(bp), free_ptr);        /* Make succ of bp “old top” */
        if(free_ptr != NULL)
            PUT(free_ptr, bp);              /* Change prev of old top to “bp” */
        free_ptr = bp;                      /* Change top of “Stack” */

        if(gamma != NULL)
            PUT(NEXT_SQR(gamma), alpha);    /* Change succ of gamma to “alpha” */
        if(alpha != NULL)
            PUT(alpha, gamma);              /* Change pred of alpha to “gamma” */
    }

    #ifdef DEBUG
        CHECKHEAP
    #endif
}
/* $end mmplace */

/* 
 * find_fit - Find a fit for a block with asize bytes 
 */
/* $begin mmfirstfit */
/* $begin mmfirstfit-proto */
static void *find_fit(size_t asize)
/* $end mmfirstfit-proto */
{
    /* $end mmfirstfit */
    /* $begin mmfirstfit */
    
    void *bp;
    bp = free_ptr;
    
    do {
        if(asize <= GET_SIZE(HDRP(bp))) {
            //printf("found fit ... %d\n", GET_SIZE(HDRP(bp)));
            return bp;
        }
        else {
            bp = GET(NEXT_SQR(bp));
        }
    } while(bp != NULL);
    
    //printf("Yes, find_fit is returning NULL\n");
    return NULL; /* No fit */
}
/* $end mmfirstfit */

static void printblock(void *bp) 
{
    size_t hsize, halloc, fsize, falloc;

    checkheap(0);
    hsize = GET_SIZE(HDRP(bp));
    halloc = GET_ALLOC(HDRP(bp));  
    fsize = GET_SIZE(FTRP(bp));
    falloc = GET_ALLOC(FTRP(bp));  

    if (hsize == 0) {
        printf("%p: EOL\n", bp);
        return;
    }
    
    if(!halloc) {
        printf("%p: header: [%ld:%c]     pred: [%p]     succ: [%p]     footer: [%ld:%c]\n", bp,
              hsize, (halloc ? 'a' : 'f'), 
              GET(bp), GET(NEXT_SQR(bp)),
              fsize, (falloc ? 'a' : 'f'));
    }
    else {
        printf("%p: header: [%ld:%c] footer: [%ld:%c]\n", bp, 
           hsize, (halloc ? 'a' : 'f'), 
           fsize, (falloc ? 'a' : 'f')); 
    }
}

static void checkblock(void *bp) 
{
    if ((size_t)bp % 8)
        printf("Error: %p is not doubleword aligned\n", bp);
    if (GET(HDRP(bp)) != GET(FTRP(bp)))
        printf("Error: header does not match footer\n");
}

/* 
 * checkheap - Minimal check of the heap for consistency 
 */
void checkheap(int verbose) 
{
    char *bp = heap_listp;

    if (verbose)
        printf("Heap (%p):\n", heap_listp);

    if ((GET_SIZE(HDRP(heap_listp)) != DSIZE) || !GET_ALLOC(HDRP(heap_listp)))
        printf("Bad prologue header\n");
    checkblock(heap_listp);

    for (bp = heap_listp; GET_SIZE(HDRP(bp)) > 0; bp = NEXT_BLKP(bp)) {
        if (verbose) 
            printblock(bp);
        checkblock(bp);
    }

    if (verbose)
        printblock(bp);
    if ((GET_SIZE(HDRP(bp)) != 0) || !(GET_ALLOC(HDRP(bp))))
        printf("Bad epilogue header\n");
    
    if ((GET_SIZE(HDRP(free_ptr))) < 3*WSIZE || (size_t)free_ptr % 8) {
        printf("Error: %p is not doubleword aligned\n", free_ptr);
    }
}

有没有人了解或知道发生了什么,或者我该如何解决?

标签: cmemory-leakssegmentation-faultmallocallocator

解决方案


推荐阅读