[英]Infinite loop in custom malloc()
我正在尝试在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);
}
您的代码中存在一个主要问题:
#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
变量。 size
是mymalloc
的参数名称,使所有这些标识符都是非恒定的。 这可能不是您的意图...
例如,无辜的测试:
if(size >= HEAP_EXTEND_SIZE)
实际上扩展到
if(size >= ((HEADER_BLK_SIZE + (((((size)-1)>>2)<<2)+4))*1024))
除非发生无符号算术溢出并且巧合地将其评估为真,否则这是错误的。
您必须先清理代码,然后才能有效地对其进行调试。
在我看来,根本原因是分配一个块后,您忘记处理freeblock点。 您需要处理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 pointeur i:0x2097004 pointeur ii:0x2097024 pointeur iii:0x209703c pointeur iiii:0x2097058
但是,我没有添加更多测试来测试是否还有其他错误。 因此,也许您需要做更多的工作来测试这一点。
如果我更改此部分:
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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.