malloc 分配大堆块(128KB)的一次探索
前言
一次意外执行了 malloc(0x5000),结构使用 gdb 调试发现其分配的位置在 TLS 区域,这令我不解(:最后去看了下 malloc 源码和 mmap 源码实现,发现似乎可能是 gdb 插件的问题,乐
场景复现
#include <stdio.h>
int main() {malloc(0x5000);return 0;
}
调试:

wtf 不应该啊,这咋能分配到 tls 区域去了呢?
问题探索
通过对 malloc 源码的查看,发现其超过了 mmap_threshold,所有最后走的 mmap 映射的一段私有匿名区域(这里大家应该都很熟悉了)所以不应该分配到 tls 区域去啊,在与 henry 师傅交流后,觉得可能与 mmap 的行为有关,于是说干就干,简单地去审了一下 mmap 的源码,最后发现可能是插件的问题
mmap 源码分析就不写了,我也没做笔记,毕竟是开源的,需要时自己去看看就行了,而且我看完 mmap 源码时已经快凌晨 3 点了,就简单说下 mmap 是如何分配虚拟内存的。在内核态,为进程维护了一颗红黑树,其根据地址组织了空闲的 vma(struct vm_area_struct 结构体表示),而在我的 ubuntu 22.04 上,文件与匿名映射区是从高地址往低地址增长的,所以 mmap 在寻找虚拟内存区域时是从高地址往低地址扫描的
知道这之后一切都可以解释了,简单调试一下,啥也不执行,看下内存布局:把随机化关了,方便调试

可以看到在 tls 前后存在 0x17e000 和 0x11000 的空间,我们来验证一下:
#include <stdio.h>
#include <sys/mman.h>
int main() {void *p0 = malloc(0x17e000-0x1000);void *p1 = mmap(0, 0x11000, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);printf("p0: %p\np1: %p\n", p0, p1);return 0;
}
我的机器上
mmap_threshold = 128kb,所以malloc(0x11000-0x1000)会走brk,所以这里我直接使用mmap
关于这里 malloc 分配为啥要减去 0x1000 请自行审计 sysmalloc 源码(大家应该比较熟悉)
调试结果如下:

可以看到 mmap 的 0x11000 区域就是 tls 下方的区域,malloc 的 0x17e000 就是 tls 前面的那块区域,这里的 gdb 插件把其当作 TLS 了似乎。当然这里可能就是 tls 预留的,我没有具体调试内核,仅仅静态分析了 mmap 的代码。当然我通过分配一些线程局部变量调整了一下 tls 区域的位置,然后也是这样的:
#include <sys/mman.h>
__thread char p0[0x17e000+0x1000];
int main() {void *p1 = mmap(0, 0x193000, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);printf("p0: %p\np1: %p\n", p0, p1);return 0;
}
调试结果:

所以当我们 malloc 超过 0x17e000-0x1000 时,就会在 libc 前面映射一段空间,也就是大家打 CTF 时说的 malloc 一块大堆块,会使用 mmap 在 libc 前面分配一个堆块,一般网上都是说分配 0x200000,其实自己简单算一算就知道了,验证一下:
#include <stdio.h>
#include <sys/mman.h>
int main() {void *p0 = malloc(0x17e000);printf("p0: %p\n", p0);return 0;
}
调试结果如下:

一切都是吻合的
一个有趣的 demo
这里给大家看一个 demo,感兴趣的可以自行研究下背后的原因
#include <stdio.h>
#include <stdint.h>
#include <string.h>int show() {FILE *maps_file;char line[256];char pathname[256];maps_file = fopen("/proc/self/maps", "r");if (maps_file == NULL) {perror("Failed to open /proc/self/maps");return 1;}while (fgets(line, sizeof(line), maps_file)) {if (sscanf(line, "%*x-%*x %*s %*x %*x:%*x %*u %s", pathname) == 1) {if (strcmp(pathname, "[stack]") == 0 || strcmp(pathname, "/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2") == 0) {printf("%s", line);}}}fclose(maps_file);return 0;
}int main() {uint64_t addr;show();puts("==========================================");scanf("%llx", &addr);*(uint64_t*)addr = 0xdeadbeef;puts("==========================================");show();return 0;
}
输出如下:

总结
mmap 的源码还是比较复杂的,我只是看了我感兴趣的部分,有兴趣的同学可以自己去看看源码,本来想说搭建环境调调 mmap 的,最后还是算了,太累了,睡觉了(:
当然这个东西本身连技术都不算,之所以记录一下,也算是回答自己刚开始学习时的一些疑问,记得当时看网上说 malloc 要分配 0x20000 才能够保证分配的空间在 libc 前面,其实根本没有问过自己为什么?也没有想过 mmap 底层是如何进行虚拟内存分配的?
当然其实现在来解决这些问题也挺好的,毕竟有一些基础,如果最开始就去看 mmap 的源码,相信我早就被劝退了
相关文章:
malloc 分配大堆块(128KB)的一次探索
前言 一次意外执行了 malloc(0x5000),结构使用 gdb 调试发现其分配的位置在 TLS 区域,这令我不解(:最后去看了下 malloc 源码和 mmap 源码实现,发现似乎可能是 gdb 插件的问题,乐 场景复现 #include <…...
Android -- 双屏异显之方法二
Android – 双屏异显之方法二: DisplayManager PS: 1. 使用改方法主板需连接至少两个输出显示屏; 2. 副屏内部实现与MediaRouter下一样;使用方法 # 主屏activity内: private SecondDisplay secondDisplay;private void dualScreen3288() {D…...
电脑使用CDR时弹出错误“计算机丢失mfc140u.dll”是什么原因?“计算机丢失mfc140u.dll”要怎么解决?
电脑使用CDR时弹出“计算机丢失mfc140u.dll”错误:原因与解决方案 在日常电脑使用中,我们时常会遇到各种系统报错和文件丢失问题。特别是当我们使用某些特定软件,如CorelDRAW(简称CDR)时,可能会遇到“计算…...
使用RDMA技术构建无损网络
如何使用RDMA构建无损网络? 在深入研究RDMA和无损网络领域后,会经常遇到两个基本问题:为什么采用无损网络至关重要?这些先进技术有什么优势? 无损网络是一种新型的网络技术,它可以在不丢失数据包的情况下传…...
vscode 识别git目录
vscode 偶尔无法识别使用git 新托管的项目。 以下是我提供的解决方案——重启 git.enabled VS Code配置问题: 有时候,VS Code的配置可能会导致无法识别.git文件夹。确保你的VS Code配置中启用了Git的相关功能。你可以通过”Settings”(设置…...
OpenCV相机标定与3D重建(26)计算两个二维点集之间的部分仿射变换矩阵(2x3)函数 estimateAffinePartial2D()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 计算两个2D点集之间的具有4个自由度的最优有限仿射变换。 cv::estimateAffinePartial2D 是 OpenCV 库中的一个函数,用于计算两个二维…...
StarRocks 生产部署一套集群,存储空间如何规划?
背景:StarRocks 3.2,存储一体 使用场景:多分析、小查询多单但不高、数据量几百T FE 存储 由于 FE 节点仅在其存储中维护 StarRocks 的元数据,因此在大多数场景下,每个 FE 节点只需要 100 GB 的 HDD 存储,…...
JVM执行引擎JIT深度剖析
前端编译与后端编译 Java 程序的编译过程是分两个部分的。一个部分是从java文件编译成为class文件,这一部分也称为前端编译。另一个部分则是这些class文件,需要进入到 JVM 虚拟机,将这些字节码指令编译成操作系统识别的具体机器指令。这一部…...
【DOCKER】基于DOCKER的服务之DUFS
文件上传下载服务器:https://github.com/sigoden/dufs # 拉取镜像 docker pull sigoden/dufs# 创建数据卷文件夹 mkdir -p /data/.docker/volumes/dufs# 创建容器 docker run -id --restartalways --name dufs \-p 51080:5000 \-v /data/.docker/volumes/dufs:/dat…...
加密货币地址的基本概念
什么是地址? 在日常生活中,地址可能指房屋、电子邮件或官网的位置,用来精确定位在系统中的特定位置或端点。在加密货币领域,地址也起着类似的基础作用,只不过是在数字环境中。 加密货币地址是区块链网络中使用的唯一…...
如何在 Linux 服务器上部署 Pydio Cells 教程
简介 Pydio Cells 是一个开源的文档共享和协作平台,专为你的组织设计。它允许你在组织内部分享文档和文件,并让你完全掌控文档共享环境。 在本教程中,我们将向你展示如何在 Alma Linux 9 服务器上安装 Pydio Cells。你将使用 MariaDB 数据库…...
Halcon例程代码解读:安全环检测(附源码|图像下载链接)
安全环检测核心思路与代码详解 项目目标 本项目的目标是检测图像中的安全环位置和方向。通过形状匹配技术,从一张模型图像中提取安全环的特征,并在后续图像中识别多个实例,完成检测和方向标定。 实现思路 安全环检测分为以下核心步骤&…...
Selenium 全面指南
Selenium 是一个强大的 Web 自动化工具,支持多种浏览器和语言绑定。 1. Selenium 的基本概念 WebDriver:Selenium 提供的核心接口,用于控制浏览器操作。显式等待:等待特定条件满足后再执行操作。隐式等待:全局设置一个…...
#error: WinSock.h has already been included解决方案
原因: 在工程中使用了 Boot 库之后,使用了socket、tcp 相关的头文件,在其他地方还是包括了头文件<windows.h>,该头文件内包含了<winsock.h>。导致遇到报错问题:WinSock.h has already been included 解决…...
2.Couchbase 的增量查询优化
在 Couchbase 中实现增量查询的优化是关键,尤其当数据量庞大时。通过合适的策略,可以显著提高增量查询的效率,确保系统在处理实时数据时的响应速度和性能。下面是一些针对 Couchbase 增量查询的优化策略。 1. 使用索引优化查询 为了提升增量…...
汽车IVI中控开发入门及进阶(46):FFmpeg
概述: FFmpeg 是领先的多媒体框架,能够解码、编码、 转码、复用、解复用、流、过滤和播放 几乎所有人类和机器创建的东西。它支持最模糊的古老格式,直到最前沿。无论它们是由某个标准委员会、社区还是公司设计的。它还具有高度的可移植性:FFmpeg 在各种构建环境、机器架构…...
Spring Boot 中的 @Scheduled 定时任务以及开关控制
Scheduled注解是Spring框架(包括Spring Boot)中用于实现定时任务的一种方式。以下是对Scheduled注解的详细解析: 一、基本概念 Scheduled注解允许开发者在Spring容器中定义定时任务。通过简单地在一个方法上添加Scheduled注解,S…...
服务器证书原理
CA(Certificate Authority)证书是由 证书颁发机构(CA)本身签名的。具体来说,这取决于 CA 的类型和其在信任链中的位置: 1. 自签名证书 根 CA 证书 是信任链的起点,由 CA 自己签名。它们是信任链…...
重温设计模式--代理、中介者、适配器模式的异同
文章目录 1、相同点2、不同点 1、相同点 目的都是为了更好地处理对象之间的关系:这三种模式都是在软件设计中用于处理对象之间的关联和交互,以达到优化系统结构、增强可维护性等目的。它们都在一定程度上隐藏了对象之间的某些细节或者复杂性,…...
2024第十六届蓝桥杯模拟赛(第二期)-Python
# 2024第十六届蓝桥杯模拟赛(第二期)-Python题解 # 自己改注释# -----------------------1------------------------ # def prime(x): # if x < 2: # return 0 # for i in range(2, int(x ** 0.5) 1): # if x % i 0: # …...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...
从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...
Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...
项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...
Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...
MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
