其实还是比较简单的,只是纯代码可能不好理解,加上图片就好理解了
要释放的内存块(绿色内存区域)左边是空闲的,就将它和左边合并,由于没有内存块数量的变化,就不需要移动内存块,对应的代码部分如下
if (i > 0) { /* 前がある */ if (man->free[i - 1].addr + man->free[i - 1].size == addr) { /* 前のあき領域にまとめられる */ man->free[i - 1].size += size;只考虑到上面的左部合并是不够的,当左右都有空闲内存块的时候,先合并到左部Free[i-1],再将Free[i]合并到新的Free[i-1],但是由于内存块数量减少了,移动内存块,这里旧的Free[i]被合并了,就需要将空闲内存块的数量-1(对应代码中的man->frees–),除此之外,还需要将之后的Free[i+1]复制到Free[i],同理Free[i+2]复制到Free[i+1],.(递归复制下去)…,复制完最后一块的时候,
代码如下
if (i > 0) { /* 前がある */ if (man->free[i - 1].addr + man->free[i - 1].size == addr) { /* 前のあき領域にまとめられる */ man->free[i - 1].size += size; if (i < man->frees) { /* 後ろもある */ if (addr + size == man->free[i].addr) { /* なんと後ろともまとめられる */ man->free[i - 1].size += man->free[i].size; /* man->free[i]の削除 */ /* free[i]がなくなったので前へつめる */ man->frees--; for (; i < man->frees; i++) { man->free[i] = man->free[i + 1]; /* 構造体の代入 */ } } } return 0; /* 成功終了 */ } }如果不是上面的情况,即Free[i-1]不在释放的内存块左侧,空闲内存块Free[i]恰好在右侧,就将内存块合并到右侧Free[i],由于没有内存块数量变化,依旧不用移动内存块。
代码如下
/* 前とはまとめられなかった */ if (i < man->frees) { /* 後ろがある */ if (addr + size == man->free[i].addr) { /* 後ろとはまとめられる */ man->free[i].addr = addr; man->free[i].size += size; return 0; /* 成功終了 */ } }如果不是上面的情况,即Free[i-1]不在释放的内存块左侧,Free[i]也不在该内存块右侧,就只能新建一个内存块,由于内存块数量改变,需要移动内存块。 首先我们需要考虑一件事,这个新建的内存块放在哪里? 因为Free[i-1]及之前都不能移动,所以只好对Free[i]及其之后下手了。 所以先而从末尾**Free[man->frees]**开始(这是空白的,因为数组是从0开始的,man->frees只表示空闲数量,所以Free[man->frees-1]才是第man->frees个有实际信息的元素),复制Free[man->frees-1]的内容到Free[man->frees],递归下去直到Free[i]复制到Free[i+1]的内容,将空闲内存块数量+1(man->frees++),,然后将Free[i]设置为刚刚释放的内存块(绿色部分)。
/* 前にも後ろにもまとめられない */ if (man->frees < MEMMAN_FREES) { /* free[i]より後ろを、後ろへずらして、すきまを作る */ for (j = man->frees; j > i; j--) { man->free[j] = man->free[j - 1]; } man->frees++; if (man->maxfrees < man->frees) { man->maxfrees = man->frees; /* 最大値を更新 */ } man->free[i].addr = addr; man->free[i].size = size; return 0; /* 成功終了 */ }由于数组Free的最大长度有限,最大空闲块数量也有限,被设置为MEMMAN_FREES=4090
#define MEMMAN_FREES 4090 /* これで約32KB */对应结构体
struct MEMMAN { /* メモリ管理 */ int frees, maxfrees, lostsize, losts; struct FREEINFO free[MEMMAN_FREES]; };超过的部分将会被记录到内存丢失信息中
/* 後ろにずらせなかった */ man->losts++; man->lostsize += size; return -1; /* 失敗終了 */