【问题标题】:Infinite loop in custom malloc()自定义 malloc() 中的无限循环
【发布时间】:2016-06-28 22:38:44
【问题描述】:

我正在尝试在 C 中实现我自己的 malloc() 函数,但我遇到了这个问题。前两个分配的地址是正确的,但之后,它不会显示其他地址。我的意思是,它陷入了无限循环。但是,如果我删除条件&& ptr->size > BLK_SIZE,它似乎工作。那么,问题是,为什么这种情况会破坏代码?除了删除条件之外,如何通过其他方式解决?

这是我的代码...

/* Author : Singh*/

typedef struct block_header {
    unsigned int size : 29,
                 zero : 2,
                alloc : 1;
} block_header;

//macros
#define HEADER_BLK_SIZE sizeof(block_header) // 4 bytes header
#define ALIGNED_PAYLOAD_SIZE (((((size)-1)>>2)<<2)+4) //to align the payload
#define BLK_SIZE HEADER_BLK_SIZE + ALIGNED_PAYLOAD_SIZE //total size of a blk
#define HEAP_EXTEND_SIZE ((BLK_SIZE)*1024) //the total heap size

static void *base_heap = NULL; //base of the heap, starting point
static void *end_heap = NULL;
static block_header *freeblk = NULL;

void *mymalloc(size_t size) {
    size_t remainder_heap = (HEAP_EXTEND_SIZE) - (BLK_SIZE);

    // first time init the heap and allocate the first block
    if (!base_heap) {
        base_heap = sbrk(0);
        end_heap = sbrk(HEAP_EXTEND_SIZE);
        if (base_heap == (void*)-1 || end_heap == (void*)-1)
            return NULL;

        block_header *blk = (block_header*)base_heap;
        blk->size = BLK_SIZE;
        blk->zero = 2;
        blk->alloc = 1;

        freeblk = ((void*)(base_heap)) + BLK_SIZE;
        freeblk->size = remainder_heap;
        freeblk->zero = 2;
        freeblk->alloc = 0;

        return ((void*)blk) + HEADER_BLK_SIZE;
    } else
    if (size >= HEAP_EXTEND_SIZE) {
        return NULL;
    } else {
    //second time and the others
        block_header *ptr = (block_header*)base_heap;
        size_t i;
        i = 0;
        while (i < (HEAP_EXTEND_SIZE)) { //travel the heap
            if ((ptr->alloc) ==1 ) { //if it's allocate we go to the nxt block
                ptr = ((void*)ptr) + ((size_t)(ptr->size));
                i += ((size_t)(ptr->size));
            } else
            if ((ptr->alloc) == 0 && ptr->size > BLK_SIZE) { /*if it's free and
                                                              big enough */
                ptr->size = BLK_SIZE;
                ptr->zero = 2;
                ptr->alloc = 1;
                return ((void*)ptr) + (HEADER_BLK_SIZE);
            } else { //not big enough so we go to the next block
                ptr = ((void*)ptr) + ((size_t)(ptr->size));
                i += ((size_t)(ptr->size));
            }
        }
        return NULL; //if it does not wok
    }
}

//for testing my code
void main() {
    int *i =(int*)mymalloc(12);
    printf("pointeur i : %p\n", i);

    int *ii = (int*)mymalloc(16);
    printf("pointeur ii : %p\n", ii);

    int *iii = (int*)mymalloc(20);
    printf("pointeur iii : %p\n", iii);

    int *iiii = (int*)mymalloc(24);
    printf("pointeur iiii : %p\n", iiii);
}

【问题讨论】:

    标签: c memory dynamic allocation


    【解决方案1】:

    你的代码有一个大问题:

    #define ALIGNED_PAYLOAD_SIZE (((((size)-1)>>2)<<2)+4) //to align the payload
    #define BLK_SIZE HEADER_BLK_SIZE + ALIGNED_PAYLOAD_SIZE //total size of a blk
    #define HEAP_EXTEND_SIZE ((BLK_SIZE)*1024) //the total heap size
    

    所有这些宏都引用了一些当前的size 变量。 sizemymalloc 的参数名称,使所有这些标识符都不是常量。这可能不是你想要的......

    例如,无辜的测试:

    if(size >= HEAP_EXTEND_SIZE)
    

    实际上扩展为

    if(size >= ((HEADER_BLK_SIZE + (((((size)-1)>>2)<<2)+4))*1024))
    

    这是假的,除非发生无符号算术溢出并且巧合地评估为真。

    您必须先清理代码,然后才能有效地调试它。

    【讨论】:

      【解决方案2】:

      在我看来,根本原因是你在分配一个块后忘记处理空闲块点。之所以需要处理freeblock点,是因为需要freeblock做一些判断。 以下是我的修改:

          else if((ptr->alloc)==0 && ptr->size > BLK_SIZE){ /*if it's free and
                                                              big enough */
              ptr->size = BLK_SIZE;
              ptr->zero = 2;
              ptr->alloc = 1;
              freeblk = ((void *)ptr) + (size_t)(ptr->size);
              freeblk->size = freeblk->size - ptr->size;
              freeblk->zero = 2;
              freeblk->alloc = 0;
              return ((void*)ptr) + (size_t)(ptr->size);
          }
      

      测试后,我发现它有效。 enter code here[zzhen201@ ~] $ ./test 指针我:0x2097004 指针二:0x2097024 指针三:0x209703c 指针iii:0x2097058

      但是,我没有添加更多测试来测试是否还有其他错误。 所以也许你需要做更多的工作来测试它。

      【讨论】:

        【解决方案3】:

        如果我改变这部分:

          else{
              block_header* ptr = (block_header*) base_heap;
              size_t i;
              i = 0;
              while(i<(HEAP_EXTEND_SIZE)){ //travel the heap
                if((ptr->alloc)==1){ //if it's allocate we go to the nxt block
                  ptr = ((void*)ptr) + ((size_t)(ptr->size));
                  i += ((size_t)(ptr->size));
                }
                else if((ptr->alloc)==0 && ptr->size > BLK_SIZE){ /*if it's free and
                                                                    big enough */
                    ptr->size = BLK_SIZE;
                    ptr->zero = 2;
                    ptr->alloc = 1;
                    return ((void*)ptr) + (HEADER_BLK_SIZE);
                }
                else{ //not big enough so we go to the next block
                  ptr = ((void*)ptr) + ((size_t)(ptr->size));
                  i += ((size_t)(ptr->size));
                }
              }
              return NULL; //if it does not wok
            }
        

        通过这部分(它不再知道空闲块是否足够大)我认为它“有效”..

        else{
              block_header* ptr = (block_header*) base_heap;
              size_t i;
              i = 0;
              while(i<(HEAP_EXTEND_SIZE)){
                if((ptr->alloc)==1){
                  ptr = ((void*)ptr) + ((size_t)(ptr->size));
                  i += ((size_t)(ptr->size));
                }
                else{
                  ptr->size = BLK_SIZE;
                  ptr->zero = 2;
                  ptr->alloc = 1;
                  return ((void*)ptr) + (HEADER_BLK_SIZE);
                }
              }
              return NULL;
            }
            return NULL;
          }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-10-30
          • 1970-01-01
          • 1970-01-01
          • 2010-11-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多