0x01:简介

在堆中的内存申请和释放中,为了减少使用系统调用函数对内存操作,malloc_state(分配区)结构中使用了fastbinsY数组和bins数组。当chunk被free后,bins链会将这些free chunk组织起来。当下次malloc时,会先对bins链中的free chunk进行遍历,有适合的则使用,无合适的再进行下一步操作。

在申请和释放操作时,一般是有一个arena(分配区,其为malloc_state结构类型)。通过宏定义bin_at(m,i)即可获得对相应bins链进行操作,m为分配区,i为索引,当i=1是为unsorted bin,i=2~63是small bin,i=64~126为large bin。

bin_at可以这样使用:
p = bin_at(m,1) //unsorted bin
FD = p -> fd //FD指向该链的第一个free chunk
BK = p -> bk //BK指向该链的最后一个free chunk

0x02:个人理解

该宏定义为这样子,主要是为了操作方便(可直接fd、bk指向)和在节省空间之间取平衡。既操作方便又不浪费空间。

bin_at(m,i)宏定义原型:

#define bin_at(m, i) \
(mbinptr) (((char *) &((m)->bins[((i) - 1) * 2])) \
- offsetof (struct malloc_chunk, fd))
解释:
1、&((m)->bins[((i)-1)*2]),该式子根据bin的索引i,i为1时,即最开始的bin(unsorted bin)。
获得bins[0]的地址,乘于2主要是因为fd和bk是一对存储的。

2、offsetof(struct malloc_chunk,fd):得到fd成员在malloc_chunk结构中的偏移量。在64位系统系统下为16。
把第一步得到地址(令其为pt)转化为char*型,这样子减偏移值: pt - offsetof = pt - offsetof*(sizeof(char))。

3、重点:
在第二步下,第一步得到的地址指向往后推移了两个单元,比如图中的bin_at(m,1)得到的是bins[0]前两个单元所在的地址。
然后经过最后的(mbinptr)转化为malloc_chunk*类型,这样就可以有->fd、->bk操作。
相当于是糊弄了操作系统,让操作系统误以为是个chunk结构。

语言表达不够,画图来凑~~

0x03:测试

 1 测试代码:
2 #include<stdio.h>
3 #include<malloc.h>
4
5 int main()
6 {
7 void* p1 = malloc(0x100);
8 void* f1 = malloc(0x10); //防止合并
9 void* p2 = malloc(0x100);
10 void* f2 = malloc(0x10);
11 void* p3 = malloc(0x100);
12 void* f3 = malloc(0x10);
13
14 sleep(0); //方便下断点
15
16 free(p1);
17 free(p2);
18 free(p3);
19
20 sleep(0); //下图断在了这里
21 return 0;
22 }

可以看出unsorted bin的第一个单元是指向bin链的第一个free chunk,另外一个单元指向bin链的最后一个free chunk。图中我已经标出了指向top chunk的那个单元,也有:bin_at(m,1)指向该单元 ,或者更本质一点:bin_at(m,1) = 0x7ffffdd1b78。

0x04:思考

在刚开始看这个宏定义时,一脸懵逼,觉得这个宏定义是有问题吧,减去16不是超出了范围了么?后来继续分析源码时发现了->fd和->bk的操作,陷入了沉思。巧的是,群里有师傅刚好提到这个问题,所以和该师傅交流了一下,最后得到了一个比较合理的解释。

但是令我疑惑的是,为什么在后面会留两个空白单元嘞?留在前面不是更恰当么?bin_at(m,1)指向了bins数组外面的单元(存top chunk地址的单元),这样会不会存有遗患呢?有想法的欢迎与我交流^_^,QQ:1623093551。


tolele 2022-03-16

关于malloc源码中的bin_at宏定义的个人见解的更多相关文章

  1. Kafka源码中的Producer Record定义

    1.ProducerRecord 含义: 发送给Kafka Broker的key/value 值对 2.内部数据结构: -- Topic (名字) -- PartitionID ( 可选) -- Ke ...

  2. Eclipse与Android源码中ProGuard工具的使用

    由于工作需要,这两天和同事在研究android下面的ProGuard工具的使用,通过查看android官网对该工具的介绍以及网络上其它相关资料,再加上自己的亲手实践,算是有了一个基本了解.下面将自己的 ...

  3. php源码分析之PHPAPI宏的作用

    在PHP源码中,我们经常会看到很多函数前面有个PHPAPI,但这是什么呢? 于是我在php源码/main/php.h中找到了它的定义 #ifdef PHP_WIN32 # include " ...

  4. Eclipse与Android源码中ProGuard工具的使用(代码混淆)

    由于工作需要,这两天和同事在研究android下面的ProGuard工具的使用,通过查看android官网对该工具的介绍以及网络上其它相关资料,再加上自己的亲手实践,算是有了一个基本了解.下面将自己的 ...

  5. 从express源码中探析其路由机制

    引言 在web开发中,一个简化的处理流程就是:客户端发起请求,然后服务端进行处理,最后返回相关数据.不管对于哪种语言哪种框架,除去细节的处理,简化后的模型都是一样的.客户端要发起请求,首先需要一个标识 ...

  6. Android 网络框架之Retrofit2使用详解及从源码中解析原理

    就目前来说Retrofit2使用的已相当的广泛,那么我们先来了解下两个问题: 1 . 什么是Retrofit? Retrofit是针对于Android/Java的.基于okHttp的.一种轻量级且安全 ...

  7. String源码中的"avoid getfield opcode"

    引言: 之前一篇文章梳理了String的不变性原则,还提到了一段源码中注释"avoid getfield opcode",当时通过查阅资料发现,这是为了防止 getfield(获取 ...

  8. android源码中修改wifi热点默认始终开启

    在项目\frameworks\base\wifi\java\android\net\wifi\WifiStateMachine.java里面,有如下的代码,是设置wifi热点保持状态的:如下: pri ...

  9. rxjava源码中的线程知识

    rxjava源码中的线程知识 rx的最精简的总结就是:异步 这里说一下以下的五个类 1.Future2.ConcurrentLinkedQueue3.volatile关键字4.AtomicRefere ...

随机推荐

  1. 类中的__getattr__ 与 __setattr__ 魔法方法

    1.__getattr__ 当我们访问一个不存在的属性的时候,会抛出异常,提示我们不存在这个属性.而这个异常就是__getattr__方法抛出的,其原因在于他是访问一个不存在的属性的最后落脚点,作为异 ...

  2. 面向对象—多态、鸭子类型(Day21)

    编程原则java具有自己的编程原则和设计模式,不能多继承.python的编程原则:1.开放封闭原则:开放是对扩展是开放的,封闭是对修改是封闭的(已经写完的代码程序是不能修改的).2.依赖倒置原则:高层 ...

  3. Linux-CPU优化之上下文切换

    为什么大量进程(通常进程数大于CPU个数)的运行会导致CPU长时间处于等待时间而导致平均负债率过高呢?没有使用CPU且无不可中断的进程,这就涉及到了上下文切换. 巧妙地利用了时间片轮转的方式, CPU ...

  4. Oracle表数据或结构误删还原

    数据误删 表结构没有发生改变 --开启表字段转移,不开启无法还原 alter table 表名 enable row movement; --数据闪回 flashback table 表名 to ti ...

  5. ios开发 Rsa签名 base64转码

    因为公司要求做了一个加密  网上的资料少有可用的  于是我看到了一位大神的曙光 但是未介绍使用方法 然后另一位大神给予了使用方法 但是没有把库给出来   我整理了一下  希望大家看的有些启发 证书生成 ...

  6. .NET 6学习笔记(1)——通过FileStream实现不同进程对单一文件的同时读写

    会写这篇纯属机缘巧合,虽然一直以来认为对单一文件的读.写操作是不冲突,可并行的,但实际并未实践过.正好有个UWP的程序要并行读取由Desktop Extension创建的文本,需要有个原型程序来验证, ...

  7. 《Java从入门到精通》学习笔记(详细)

    目录 03 Java语言基础 基本数据类型 变量与常量 运算符 类型转换 代码规范 标识符命名规范 常用输入输出 04 流程控制 条件语句 循环语句 循环控制 练习 05 字符串 创建字符串 连接字符 ...

  8. 60天shell脚本计划-2/12-渐入佳境

    --作者:飞翔的小胖猪 --创建时间:2021年2月1日 --修改时间:2021年2月5日 说明 每日上传更新一个shell脚本,周期为60天.如有需求的读者可根据自己实际情况选用合适的脚本,也可在评 ...

  9. 量化研究之“大A打板敢死队”是如何做换手板与撬板的?

    更多精彩内容,欢迎关注公众号:数量技术宅,也可添加技术宅个人微信号:sljsz01,与我交流. 涨停跌停板分类 涨停.跌停是A股特有的现象,其他主要市场,例如美股.港股都不存在涨跌停的规则.涨停.跌停 ...

  10. javaweb添加日常基本依赖

    <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql ...