• A+

在写题的时候遇到了一个诡异的问题。去请教了槐师傅,学到了一点带源码调试的技巧,于是尝试手动调试了好久才找到大致原因,归根结底还是没有把glibc中各种堆相关的实现和宏看得足够明白,以至于忽略了一些可能会引起错误的机制。

参考链接:

glibc-2.23 source code:https://elixir.bootlin.com/glibc/glibc-2.23/source/malloc/malloc.c
malloc_consolidate:https://blog.csdn.net/qq_41453285/article/details/97627411

草...居然不想写了

两种奇妙的情况

一下两种情况的堆构造只有最前面有无一个被free掉的fastchunk的区别,其它fakechunk的构造均相同

第一种,可以发生Unlink

[笔记] 在发生Unlink时一个要注意的细节

第二种,Unlink时会提示prev_size错误

[笔记] 在发生Unlink时一个要注意的细节

和我一起想想想

为啥前面多了一个free的fastchunk就会错误呢....

动态调试结合相关源码阅读,在glibc中找到了这么一段关键代码:
(glibc-2.23 malloc.c:4074)

    if ((unsigned long)(size) >= FASTBIN_CONSOLIDATION_THRESHOLD) {
      if (have_fastchunks(av))
	malloc_consolidate(av);

当被free的size大于FASTBIN_CONSOLIDATION_THRESHOLD 这个常量时,系统会认为当前零散内存块较多,会触发所有被free的fastchunk的重新回收整理,与周围的freechunk合并。

而由于small chunk挨着top chunk,在和fakechunk合并之后会立马和top chunk合并,从而触发了 CONSOLIDATION 机制。同时继续往下跟进发现fastchunnk在与周围freechunk合并的过程中同样要经过unlink宏的检查,由于我们之前构造过fakechunk,所以按照正常遍历顺序,检查prev_size的时候是错位的,这就会导致检查不通过,发生报错。并不是没和fakechunk合并成功,而是没和fastchunk合并成功。

总结

再次出现这种不得已的情况时要么不要让开头出现free的fastchunk,要么想办法使smallchunk和top chunk隔开。一般在控制能力较强的时候选用第二种方法,但是有的题实在限制太严格,就容易出现这种窘境。

eqqie

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: