【发布时间】:2018-07-16 15:17:09
【问题描述】:
让我们看看这个给定的代码:
void free(void *ap) {
Header *bp, *p;
bp = (Header *)ap - 1;
for (p = freep; !(bp > p && bp < p->s.ptr); p = p->s.ptr)
if (p >= p->s.ptr && (bp > p || bp < p->s.ptr))
break;
if (bp + bp->s.size == p->s.ptr) {
bp->s.size += p->s.ptr->s.size;
bp->s.ptr = p->s.ptr->s.ptr;
} else
bp->s.ptr = p->s.ptr;
if (p + p->s.size == bp) {
p->s.size += bp->s.size;
p->s.ptr = bp->s.ptr;
} else
p->s.ptr = bp;
freep = p;
}
据我所知,如果这个给定的 free 得到一个指向已经存在的内存块的指针,这个循环:
for (p = freep; !(bp > p && bp < p->s.ptr); p = p->s.ptr)
if (p >= p->s.ptr && (bp > p || bp < p->s.ptr))
break;
实际上将永远存在。 因为当 p==ap 并且对于每个其他 p 条件:!(bp > p && bp s.ptr) 将是真的 并且条件 p >= p->s.ptr && (bp > p || bp s.ptr) 将为假。
编辑: 完整的代码可以在这里看到: Explain this implementation of malloc from the K&R book
【问题讨论】:
-
什么是
Header?freep是什么?s是什么?请出示minimal reproducible example。 -
顺便说一句:我不确定从一本 30 年前的书中学习 C 是否真的是个好主意。
-
@MichaelWalz:我愿意。恕我直言,它仍然是 C 的最佳展示。确实,那么您应该继续深造。
-
分配器假设以前分配的块将来可能有用是很正常的。所以不,它不会释放内存,它可以用于将来的 malloc() 调用。更复杂的分配器也将与操作系统合作以释放地址空间,通常是在足够的连续空间再次可用时,但依赖于操作系统实现肯定不是代码的重点。