高并发内存池 - 申请内存过程联调 📅 发布时间:2026/7/13 5:56:00 👁️ 浏览次数: 高并发内存池 - 申请内存过程联调到此我们已经将内存池中 “申请内存” 功能的逻辑实现的七七八八了接下来我们将设计一个测试函数看看目前的功能是否能跑通。UintTest.cpp#includeComm.h#includeConcurrentAlloc.hvoidAlloc1(){void*ptr1ConcurrentAlloc(1);void*ptr2ConcurrentAlloc(2);void*ptr3ConcurrentAlloc(3);void*ptr4ConcurrentAlloc(4);void*ptr5ConcurrentAlloc(5);void*ptr6ConcurrentAlloc(6);void*ptr7ConcurrentAlloc(7);void*ptr8ConcurrentAlloc(8);}voidAlloc2(){for(inti0;i5;i)void*ptrConcurrentAlloc(7);}intmain(){Alloc1();Alloc2();std::cout第一阶段测试成功std::endl;return0;}下面讲讲我在此次测试中其中出现的 BUG以及错误原因是什么如何调试的1. 野指针问题在 Page Cache 的实现中出现了野指针问题Span*spanN_spanLists[i].PopFront();Span*spanK;//踩的第一个坑没有申请空间野指针直接使用spanK-_pageIdspanN-_pageId;spanK-_nk;spanN-_pageIdk;spanN-_n-k;_spanLists[spanN-_n].PushFront(spanN);//踩的第三个坑把 spanK 挂上去了returnspanK;可以看到我在Span* spanK后并没有 new 创建一个对象这导致了野指针问题程序直接发生了崩溃。对于 bus error 的错误我是第一次遇见在此之前的 BUG 基本靠着调试都可以找到崩溃那一步从而去向上推演但这次不一样一步一步调试无法在给我任何信息。并没有跳到崩溃的那一步去所以一步一步调试已经无法解决这个问题在询问过 AI 后我开始使用 lldb 去解决这个问题。此时使用 run 指令观察指针就会发现指针地址为 0x0000000000000001很明显出现了野指针问题0x0000000000000001 指针不会是正常开辟出来的因为实在是太小了直接指向核心区低地址所以一定是指针没有初始化造成了野指针问题我开始一步一步向上排查。在我尝试 bt 后发现并没有本应呈现的调试信息并没有展现甚至是在我编译已经加了 -g 的情况下此时说明栈已经被彻底破坏了到此基本就可以判定一定是野指针问题指针未被初始化就直接使用。但是本次调试最难的点就在于栈已经被破坏。这意味着无法再输出更多的调试信息栈帧的结构为这样高地址 ------------------ | 返回地址 (RA) | ← 函数执行完后CPU 要跳回哪里继续执行 | 旧帧指针 (FP) | ← 上一个函数的栈帧起点用于回溯调用链 | 局部变量 | ← 你定义的数组、结构体、临时变量 | 参数区 | ← 传给下一个函数的参数 ------------------ 低地址 ← sp (栈指针)当代码中出现缓冲区溢出、野指针写栈、链表越界写时写入的数据可能冲破了局部变量的边界直接覆盖了返回地址或帧指针------------------ | 返回地址 (RA) | ← 原本存的是 0x100005678 (main24) | 旧帧指针 (FP) | ← 原本存的是 0x16fdfd000 ------------------ | 局部变量 buf[8] | ← 你的代码写了 buf[10] 0x1 ------------------buf[10] 写到了返回地址的位置把 0x100005678 改成了 0x1。当函数执行到 return 时CPU 从栈上取出返回地址准备跳回去。但它取到的是被覆盖后的 0x1于是CPU 试图在地址 0x1 执行指令0x1 不是有效的代码地址触发 EXC_BAD_ACCESS调试器问栈“你是谁调用的” 栈说“我不知道我的帧指针和返回地址都被人改了。”于是 bt 只能显示当前这一帧 0x1上面一片空白这就是 “栈被彻底破坏”不是数据错了而是现场记录本身被销毁了。所以这也是这个 BUG 最难排查的点不过我尝试从 Page Cache 层向上排查定义指针变量的位置然后逐一寻找最后还是锁定了出错位置解决了这个问题。当然这其中有很多的调试工具可以使用例如 ASan、watchpoint 等但我对这些了解也不是深所以没有办法讲解如何依靠这些工具进行调试后续的学习中我会将这方面能力补上。2. 内存垃圾值问题在 Thread Cache 中我手滑将没有调整的空间字节大小传入造成了第二个很麻烦的问题。void*ThreadCache::Allocate(size_t size){assert(sizeMAX_BYTES);size_t alignsizeSizeClass::RoundUp(size);size_t indexSizeClass::Index(size);if(!_freeList[index].Empty()){return_freeList[index].Pop();}else{//从中心缓存获取数据returnFetchFromCentralCache(index,size);//踩坑一开始传入的不是alignsize导致读出了垃圾值}}所以出现了下面的报错情况:这次产生的是段错误这里有了上面的经验我开始使用 lldb 调试。这里出现了调试信息代表可能并非野指针问题但是这里的地址值很有趣 0x807060504030201是一个递减的数列我的直觉告诉我程序崩溃的秘密就藏在这串地址中于是我去询问了 AI 这串地址的具体含义这种地址叫做内存垃圾值。下面我们讲解一下什么叫做内存垃圾值内存中的垃圾值不是一团乱码它们有明确的来源和可识别的模式来源典型值64位含义识别特征未初始化栈变量0xcdcdcdcdcdcdcdcdMSVC/clang Debug 填充连续CD已释放堆内存0xddddddddddddddddMSVC “Dead Memory”连续DD已释放栈内存0xccccccccccccccccMSVC 栈释放标记连续CCmmap 新分配0x0000000000000000操作系统清零全零越界读取拼接0x807060504030201你遇到的有规律但不统一安全金丝雀0xfd7a3e9c2b1d405f栈保护随机值完全随机关键洞察0x807060504030201 属于越界读取拼接值——它不像 CDCDCDCD 那样来自编译器填充而是代码自己把相邻内存的数据块拼成了一个 64 位整数。假设 mmap 分配了一块 8KB 的内存起始地址是 0x100000000简化假设。系统出于安全考虑会把匿名映射内存清零所以初始状态是地址 内存内容 0x100000000: 00 00 00 00 00 00 00 00 0x100000008: 00 00 00 00 00 00 00 00 0x100000010: 00 00 00 00 00 00 00 00 ...现在 GetOneSpan 用 size2 构建自由链表startsize;// start 0x100000002void*tailnewSpan-_freelist;// tail 0x100000000while(startend){ObjNext(tail)start;// 向 tail 写入 8 字节指针tailObjNext(tail);// 从 tail 读取 8 字节指针startsize;// start 2}第一次循环tail 0x100000000ObjNext(tail) 0x100000002向地址 0x100000000 写入 8 字节小端序下内存变成02 00 00 00 01 00 00 00tail ObjNext(tail)读取出来是 0x100000002第二次循环tail 0x100000002ObjNext(tail) 0x100000004向地址 0x100000002 写入 8 字节这会覆盖 0x100000002 到 0x100000009 的内存灾难发生第一次写入在 0x100000000 的数据是地址: 0 1 2 3 4 5 6 7 内存: [02 00 00 00 01 00 00 00]第二次写入在 0x100000002 覆盖后地址: 0 1 2 3 4 5 6 7 内存: [02 00 04 00 00 00 01 00] // ↑ 从这里开始被覆盖链表已经彻底混乱了。 每个节点只有 2 字节但写入是 8 字节导致每个写入都在覆盖前面节点的数据。当 FetchRangeObj 来读取时endstart;// end 0x100000000ObjNext(end);// 从 0x100000000 读取 8 字节此时 0x100000000 处的内存已经被多次覆盖可能变成了内存字节: 01 20 30 40 50 60 70 80在小端序ARM64/macOS下CPU 读取这 8 个字节为一个 64 位指针时字节 0 (01) 是最低有效字节字节 7 (80) 是最高有效字节组合结果0x807060504030201所以就造成了地址的递减情况幸运的是 0x807060504030201 并不指向合法地址处所以产生了崩溃使我们可以观察到问题如果恰好指向合法地址处那么恐怕会隐藏的更深。继续调试现在通过 bt我们可以观察到调用的堆栈结构接着逐一向上排查网上排查了一层观察一下变量的值逐一去查看他们是否正确其实到这一步就已经初见端倪了size 的值应该是 8但是却为 2所以排查出了是 size 的问题最终也成功解决这个 BUG。其实中途还解决了一些 BUG不过都是些很简单的错误没有什么有趣的现象和值得深度挖掘的东西就不在这里讲述了我们下篇文章再见。
VSCode EIDE 插件 v3.27.2 配置:从 Keil MDK 到 STM32 项目的 3 步迁移指南 VSCode EIDE 插件 v3.27.2 配置:从 Keil MDK 到 STM32 项目的 3 步迁移指南对于习惯了 Keil MDK 开发环境的嵌入式工程师来说,迁移到 VSCode 可能是一个令人望而生畏的过程。然而,借助 EIDE 插件,这一过程可以变得异常简单。本文将… 2026/7/13 5:51:59
Windows 11专业工作站版一键重装指南:从官方工具到U盘启动 这次我们来详细聊聊如何在普通电脑上自己动手重装 Windows 11 专业工作站版系统。对于很多用户来说,系统重装一直是个技术活,要么花钱找维修师傅,要么冒着风险使用来路不明的重装工具。其实只要掌握正确方法,自己重装系统可以很简… 2026/7/13 5:51:59
Slash Commands:把反复重打的提示词,固化成团队命令 TL;DR: Slash Commands 是 .claude/commands/ 里的 Markdown 文件,按需加载,用 $ARGUMENTS 参数化。它解决的是"第三次重复写同一段提示词"的问题——把高频、短流程的任务固化成版本化文件,消除提示词漂移,… 2026/7/13 5:51:59
ADS7828与PIC32MZ的嵌入式信号采集系统设计 1. 项目背景与核心器件选型在嵌入式系统开发中,模拟信号采集是连接物理世界与数字系统的关键环节。ADS7828作为德州仪器(TI)推出的12位精度ADC芯片,以其低功耗特性(工作电流仅250μA)和8通道多路复用能力,成为中精度数据采集的理想选择。搭配… 2026/7/13 7:10:38
STM32F303VE GPIO上拉下拉配置与信号完整性优化 1. 信号上拉与下拉的基础原理在嵌入式系统设计中,信号线的上拉和下拉配置是确保电路可靠工作的基础。上拉电阻将信号线拉向高电平(通常接VCC),而下拉电阻则将信号线拉向低电平(通常接GND)。这种配置在数字电… 2026/7/13 7:10:38
Spark 3.5.0 与 Hadoop 3.3.6 环境变量冲突排查:5 个关键配置项详解 Spark 3.5.0 与 Hadoop 3.3.6 环境变量冲突排查:5 个关键配置项详解当企业级大数据平台从传统Hadoop生态向Spark计算引擎迁移时,环境变量配置不当导致的兼容性问题成为最常见的"拦路虎"。本文将深入剖析Spark与Hadoop集成时最易引发冲突的5个核… 2026/7/13 7:10:38
高压安全隔离技术:ISOM8710在工业控制中的应用 1. 高压安全隔离的必要性与挑战在工业控制、医疗设备和新能源系统中,高压安全隔离是确保人员和设备安全的关键技术。想象一下,当你的电路板需要处理380V交流电时,如果隔离失效,操作人员触摸控制面板的瞬间就可能遭遇致命电击。这就… 2026/7/13 7:10:38
Jumbled Word Game设计原理与教育应用 1. 这不是拼字游戏,而是一场大脑的“抗干扰训练”“Jumbled Word Game”——光看名字,很多人第一反应是“哦,就是把字母打乱让人猜单词嘛”,类似小时候语文课上的填字游戏或者手机里消消乐式的文字解谜。但如果你真这么想… 2026/7/13 7:08:36
直流负载管理中的G6D-ASI继电器与PIC18F47Q10应用 1. 直流负载管理的核心挑战与优化思路在工业自动化和电力电子领域,直流负载管理一直是个既基础又关键的课题。我最近在一个太阳能充电控制项目中,深刻体会到了传统方案的局限性——当面对动态变化的负载时,简单的开关控制会导致明显的效率损失… 2026/7/13 7:08:36
HS2-HF Patch终极指南:如何用3步解决Honey Select 2的70+个痛点 HS2-HF Patch终极指南:如何用3步解决Honey Select 2的70个痛点 【免费下载链接】HS2-HF_Patch Automatically translate, uncensor and update HoneySelect2! 项目地址: https://gitcode.com/gh_mirrors/hs/HS2-HF_Patch 你是否曾经在Honey Select 2中遇到过… 2026/7/13 0:01:19
语音转文字工具AsrTools:让音频整理变得简单高效 语音转文字工具AsrTools:让音频整理变得简单高效 【免费下载链接】AsrTools ✨ AsrTools: Smart Voice-to-Text Tool | Efficient Batch Processing | User-Friendly Interface | No GPU Required | Supports SRT/TXT Output | Turn your audio into accurate text … 2026/7/13 0:03:19
基于深度学习的蘑菇或花卉或动漫人物或中草药货水果蔬菜等识别系统31(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_ 基于深度学习的蘑菇或花卉或动漫人物或中草药货水果蔬菜等识别系统31(设计源文件万字报告讲解)(支持资料、图片参考_相关定制)_ 独家界面!不会重复,此项目属于本人原创,若有雷同,均是盗卖,各位买… 2026/7/13 0:05:20
Git reset 与 revert 深度对比:5个关键差异与 3 种典型应用场景 Git Reset 与 Revert 深度对比:5个关键差异与3种典型应用场景在团队协作开发中,代码版本管理如同行走钢丝——一步失误可能导致整个项目陷入混乱。作为Git进阶用户,你是否曾在深夜面对错误的提交束手无策?是否在强制推送后收到同事… 2026/7/12 0:01:13
GitHub 学生包申请避坑:5个常见失败原因与开发者工具调试方案 GitHub 学生包申请技术排障指南:5个高频失败场景与开发者工具实战方案第一次尝试申请GitHub学生包时,我盯着屏幕上那个不断转圈的加载动画整整15分钟,最终只等来了一行冰冷的错误提示。这可能是许多开发者共同的经历——明明按照教程操作&… 2026/7/12 0:01:13
冒烟测试用例设计规范:5%-10%覆盖率下的3类核心场景与执行标准 冒烟测试用例设计的黄金法则:5%-10%覆盖率下的精准筛选策略在快节奏的敏捷开发环境中,冒烟测试作为质量保障的第一道防线,其重要性不言而喻。当测试资源有限而时间紧迫时,如何从海量测试用例中精准筛选出那关键的5%-10%࿰… 2026/7/13 2:34:55