c语⾔malloc源码详解,dlmalloc源码剖析之:mALLOc /*如果你使⽤linux, douglea malloc已经默认作为glibc的malloc,
新的版本可能⽤的是ptmalloc(dlmalloc的多线程版本)
如果你⽤的bsd4.2及以前系统libc⽤的kingsley的malloc;
BSD(包括freebsd,netbsd,openbsd)4.2以后版本libc⽤的是PHKmalloc;
如果你⽤的windows系统⽤的是microsoft的分配器算法;
不过其他各个系统很容易使⽤doug lea malloc替换现有的malloc*/
//c语⾔标准库提供的malloc函数;请注意malloc的⼏个return出⼝;
void* mALLOc(size_t bytes)
{
//0~4bytes->nb=16;>4bytes->nb=bytes+2个4字节头,然后对其到8bytes
checked_request2size(bytes, nb);
//如果在fastbin中有可⽤的块直接从fastbin中分配
if ((unsigned long)(nb) <= (unsigned long)(av->max_fast)) {
fb = &(av->fastbins[(fastbin_index(nb))]);
if ( (victim = *fb) != 0) { //静态变量成员fastbin初始化为0
*fb = victim->fd;
check_remalloced_chunk(victim, nb);
return chunk2mem(victim);
}
}
//如果是<512bytes的⼩块请求,从smallbin中取⼀块
if (in_smallbin_range(nb))
{
//根据nb⼤⼩定位到smallbin
idx = smallbin_index(nb);
bin = bin_at(av,idx);
molloc函数//如果该⼤⼩的bin列表不为空
if ( (victim = last(bin)) != bin)
{
if (victim == 0) //静态变量成员smallbin初始化是0
malloc_consolidate(av);//第⼀次进来这⾥调⽤init_state函数进⾏初始化
else {//有空闲块
/* victim
|
\/
bin->first_chunk->chunk->chunk->...->last_chunk
| /\
--------------------------------->|
*/
//按上图将victim从链表中删除,设置victim的下⼀块的pbit=inuse
//将victim块返回给应⽤
return chunk2mem(victim);
}
}
}
else {//>512bytes,先释放fastbin中的块
idx = largebin_index(nb);
if (have_fastchunks(av)) //初始化的时候静态变量0,这个条件成⽴,
malloc_consolidate(av); //合并fastbin中的chunk,放⼊unsorted_bin
}
//这⾥是唯⼀将chunks放⼊bin的地⽅
//处理最近被释放或剩余的chunks,如果上次⼩请求没有完全匹配
//分割出⼩chunk就会发⽣
//最外⾯的for(;;)需要,因为我们⽆法知道在malloc结束前有合并操作
//因此需要多尝试⼀次,最多多循环⼀次
for(;;){
/*
unsorted chunks,所有的从⼀个chunk中分割出来的剩余chunk⾸先放到
unsorted chunks链表中,下次malloc调⽤中有⼀次被再次使⽤的机会。
作为⼀个队列维护。
当free或malloc_consolidate函数中 将剩余chunk放⼊unsorted chunks链表,
⽽在malloc函数中被分配或放⼊其他 正常bin中。
*/
//循环unsorted中每⼀块,与插⼊顺序相反,从后⾯开始匹配查
while ( (victim = unsorted_chunks(av)->bk) != unsorted_chunks(av)) {
bck = victim->bk;//victim:unsorted's last chunk;bck:unsorted's last-two chunk size = chunksize(victim);
if (in_smallbin_range(nb) //<512bytes
&& bck == unsorted_chunks(av) //unsorted队列中只有⼀块
&& victim == av->last_remainder //并且这⼀块是上⼀次分割剩下的
&& (unsigned long)(size) > (unsigned long)(nb + MINSIZE)) //剩余的chunk必须⼤于MINSIZE {
//分割nb出去,剩余的继续放在reminder和unsorted中
return chunk2mem(victim);
}
//unsorted_bin中多于⼀块chunk,或者剩余⼀块但不是上⼀次分割剩余的
//或者剩余的⼀块⼤⼩太⼩,继续向下
//把最后⼀块从unsorted freelist中删除
unsorted_chunks(av)->bk = bck;
bck->fd = unsorted_chunks(av);
//如果正好完全匹配,则return
if (size == nb) {
set_inuse_bit_at_offset(victim, size);
check_malloced_chunk(victim, nb);
return chunk2mem(victim);
}
//不是完全匹配就从unsorted_bin移到normal_bin中
if(in_smallbin_range(size)){}
else//注意large-bin中的内存块是有序的,FIFO
{}
}//end while
//对于<512bytes的请求,使⽤best-fit策略查当前bin
//注意当前bin是根据应⽤请求的size直接index定位到的bin
if (!in_smallbin_range(nb)) {//best-fit
if ((victim = last(bin)) != bin //empty or //first最⼤,但也不能满⾜请求
&&(unsigned long)(first(bin)->size) >= (unsigned long)(nb)) {
//从后往前,到第⼀个满⾜请求的
while (((unsigned long)(size = chunksize(victim)) < (unsigned long)(nb)))
victim = victim->bk;
//如果剩余的⼤⼩
if (remainder_size < MINSIZE) {
else{//分割该块,返回给应⽤,剩余的块 放⼊unsorted-bin
return chunk2mem(victim);
}
}
}
//如果unsorted-bin,当前bin都没有满⾜的,依次查下⼀个更⼤的bin,直到到⼀个满⾜的为⽌for (;;) {
//这⾥使⽤了bitmap技巧快速查到匹配的large-bin,具体信息可以参考其他⽂章
//bit > map说明这个32位中bit后⾯的bin都是空
/*bit==0??啥意思,index%32==0
index->bit
32 ->1 2^0
1 ->
2 2^1
2 ->4 2^2
...
31 -> 2^31
*/
if (bit > map || bit == 0) {//bit怎么会是0 //从下⼀个32开始
do {
if (++block >= BINMAPSIZE) /* out of bins */
goto use_top; //所有bin都完了还没到,跳到下⾯use_top
} while ( (map = av->binmap[block]) == 0);
bin = bin_at(av, (block << BINMAPSHIFT));
bit = 1;//从第⼀位开始
}
//......
//如果到⼀块满⾜的,将该块进⾏分割
//如果剩余的⼤⼩
if (remainder_size < MINSIZE) {
return chunk2mem(victim);
}
else{//分割该块,返回给应⽤,剩余的块 放⼊unsorted-bin
}//end for(;;),遍历normal-bin
/
/如果所有bin都没有可⽤的块
use_top:
//如果top⾜够⼤,从top取⼀块return给⽤户,修改top指针
if ((unsigned long)(size) >= (unsigned long)(nb + MINSIZE)) { return chunk2mem(victim);
}
//上⾯⼊⼝处如果请求>512bytes会触发合并fastbin
//在这⾥:如果fastbins⽆法满⾜,smallbins也⽆法满⾜,
//⽽后合并fastbins放⼊unsorted_bins,
//对于⼤块再到unsorted_bins,如果没有精确匹配放⼊normal_bin //然后再到normal_binsbest-fit
//如果还没到,扩展top
//由此可知,如果请求smallsize,则不会触发上述合并fastbins,
/
/然后会触发到unsorted_bins查,只有⼀块上次剩余的⼩块才会//被分配,或者精确匹配,否则放⼊normal_bins
//然后不管larger或small都到normal_bins中查
//所以在这⾥对fastbins合并再尝试⼀次
else if (have_fastchunks(av)) {
assert(in_smallbin_range(nb));
malloc_consolidate(av);
idx = smallbin_index(nb); /* restore original bin index */
}
else //top也没法满⾜,向OS扩展内存
return sYSMALLOc(nb, av);
}
}//最外层的for(;;)
//end
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论