realloc 失败时原指针仍然有效:`p = realloc(p, n)` 这一行漏掉了一个临时变量

发布时间:2026/10/30 13:13:58

realloc 失败时原指针仍然有效:`p = realloc(p, n)` 这一行漏掉了一个临时变量 本文首发于 CSDN。结论都能用手册原文核对代码可以照着跑。一段跑了两年的日志采集程序某天被投诉「偶尔丢日志」。不是全丢是每次 OOM 前后丢掉最后几行。查了两天。程序的写法是这样的char*bufmalloc(1024);size_tcap1024;/* ... 读数据满了就扩容 ... */bufrealloc(buf,cap*2);cap*2;strcpy(bufused,line);重试逻辑对扩容逻辑对读逻辑也对。问题在那句赋值上realloc失败时返回NULL赋回buf之后原来那块内存的地址就丢了——既没释放也再也拿不到。紧接着strcpy往NULL上写程序崩在无关的地方而崩之前那几行日志已经写进「丢失的旧块」里。手册对失败的定义比大多数人以为的严格realloc的 RETURN VALUE 有一句话很多人从没读到那一行If these functions fail, the original block is left untouched; it is not freed or moved.失败时原块保持不变既不释放也不移动。这句话反过来读就是失败之后你还持有原指针它仍然有效你可以继续用它或者主动free掉。丢失地址不是realloc干的是那句赋值干的。正确的写法只有一个形状——先收进临时变量void*tmprealloc(buf,cap*2);if(tmpNULL){/* 原块还在buf 仍可用这里决定是退出还是保留旧容量 */free(buf);return-1;}buftmp;cap*2;还有三个附带结论同样写在手册里第一realloc可能搬家。the returned pointer may be the same as p if the allocation was not moved … or different from p if the allocation was moved to a new address.所以任何缓存了旧指针的地方链表节点、外部结构体、别的线程在realloc之后都必须更新否则就是悬垂指针。第二realloc(p, 0)在 glibc 上是个坑。手册的 BUGS 一节写得很直接The glibc implementation of realloc() is not consistent with that, and as a consequence, it is dangerous to call realloc(p, 0) in glibc.给出的绕法也很简单realloc(p, size ? size : 1)。真要释放就直接free别用realloc(p, 0)表达「缩到零」。第三reallocarray能挡住乘法溢出。手册对malloc(n * size)这种写法明确提了If the multiplication of n and size would result in integer overflow, then calloc() returns an error. By contrast, an integer overflow would not be detected in the following call to malloc()reallocarray(p, n, size)做的就是把这道检查加上。扩容逻辑里凡是「元素个数 × 元素大小」的乘法都该用它。为什么这个 bug 只在 OOM 时出现因为它需要一个「分配失败」的条件才会触发。条件触发概率现象机器内存充足几乎为零完全正常测试环境永远看不到容器内存接近上限低偶发崩溃日志里最后几条丢失开了 overcommit更低realloc返回非空真正写的时候才 OOMKill有RLIMIT_AS限制中可稳定复现但需要专门构造最后一行值得多说。手册 NOTE 里写了 Linux 默认的乐观分配策略when malloc() returns non-NULL there is no guarantee that the memory really is available也就是说realloc返回非空不代表内存真的到手了。这条会让「用返回值判断是否 OOM」的思路在高负载下失效进程可能直接被 OOM killer 干掉连失败分支都走不到。真正可控的复现方式是用setrlimit设一个RLIMIT_AS上限把分配压到失败。我们后来把它写进了单测每个扩容点都跑一次「限制到刚好不够」的用例。换成预分配加分段能省掉什么如果逻辑允许把「反复扩容」换成「按块分配 块指针数组」就不需要realloc了structchunk{char*p;size_tlen;};staticstructchunkchunks[64];/* 每块固定 64KB满了就开下一块永不 realloc */代价是读取时要跨块拼接收益是没有搬家、没有失败分支、没有悬垂指针。日志采集这种「只追加、不随机访问」的场景分段几乎总是更省心。顺带说两句工具valgrind能查泄漏但查不出「丢了指针」——因为那块内存在进程退出时还在只是没人引用。-fsanitizeaddress能抓住「往 NULL 上写」这个后果但抓不住根因。真正能抓住根因的是代码审查规则凡是对realloc的返回值直接赋给原指针的写法一律标记为可疑。这条规则执行下来我们代码库里同类写法清掉了十七处。这类基础题我先按手册条目编号把草稿归档归档表用 AI墨衍 维护再在 CSDN 上写成文章会员的发文额度够我一口气把一批草稿都存下来GEO 检测能看出文章在 AI 搜索里有没有被引用图文同步则省掉了每个平台重排一遍的时间https://mp.csdn.net/vip?utm_sourceITmoyan常见问题Qrealloc失败之后直接free(buf)对吗对。原块还在free它会正常释放。前提是这句赋值没发生——一旦buf NULL就没有块可释放了。Qrealloc(NULL, n)等价于malloc(n)吗等价。手册原文「If p is NULL, then the call is equivalent to malloc(size)」。Q缩小容量会不会失败一般不会但可能发生搬家。缩小也可能返回新地址所以临时变量的写法对缩小同样适用。Qcalloc和malloc哪个更适合数组calloc。它在乘法溢出时返回错误而malloc(n * size)不检查溢出calloc还顺手把内存清零。Q为什么我的程序在realloc之后指针值变了但数据没丢因为数据被拷到了新地址。realloc保证「从块首到新旧尺寸较小者」的内容不变但新地址需要重新取旧地址立即失效。Q容器里 C 程序的 OOM 是什么表现多数情况是被 cgroup 直接 OOMKill进程收不到NULL也就走不到失败分支。这时候看dmesg比看日志有用。写在最后这次修复只改了一行搬移但引出一个更值得记住的判断库里返回NULL的失败往往不是「什么都发生了」而是「什么都没发生」。realloc失败时什么都没发生是你自己的赋值把它变成了「发生了」。我后来把这批分配函数的「失败后的正确动作」整理成了一张表散在几个项目的编码规范里底稿是用 AI墨衍 把手册条目按「操作 / 失败后指针是否有效 / 该做什么」三列排出来的几份文档之间同步一次就够。查表比凭记忆稳。想要把发文额度、GEO 检测、图文同步一起用起来的话入口在这里https://mp.csdn.net/vip?utm_sourceITmoyan
延伸阅读

更多相关文章

2026/10/30 13:13:58

Java三国杀源码解析:从环境搭建到技能扩展的实战指南

简介:这是一份基于Java语言实现的三国杀游戏项目源文件,面向对卡牌游戏开发、Java面向对象编程及游戏逻辑实现感兴趣的开发者与学习者。项目Alpha 0.5.11版本已基本实现标准版25个武将、104张牌的全部技能,将复杂的桌面游戏规则抽象为可执行的…

2026/10/30 13:13:58

YOLOX+ByteTrack在OpenCV+ONNX Runtime部署避坑指南

简介:本资源是一套面向计算机视觉开发者与算法工程师的端到端目标跟踪实践方案,聚焦YOLOX检测与ByteTrack跟踪在OpenCVONNXRuntime框架下的跨语言部署。资源提供C与Python双版本完整实现,覆盖模型加载、预处理、推理、后处理及多目标关联全流…

2026/10/30 13:13:58

数据中心接入交换机架构:TOR、MOR与EOR详解

1. 数据中心接入交换机的三种核心架构解析 在数据中心网络设计中,接入交换机的部署架构直接影响着网络性能、运维效率和成本控制。从业十五年来,我见证过各种架构在实际环境中的表现差异。今天我们就来深入拆解EOR(End of Row)、M…

2026/10/30 14:19:18

Seedance 2.0 提示词工程:结构化指令与可执行校验指南

简介:本资源是面向AI视频创作者与提示词工程师的Seedance 2.0实战指南,聚焦字节跳动即梦平台核心视频模型的高效应用,解决从提示词零基础到精准控场的关键瓶颈。压缩包共3个文件(14KB),含可直接运行的.insc…

2026/10/30 14:19:18

Oracle SQL Developer免安装版连接配置与排障实战

简介:Oracle SQL Developer 4.0.3.16.84-x64 是面向Oracle数据库开发人员与DBA的64位免费图形化管理工具,适合初学者建立连接、编写SQL,也适合有经验者进行数据建模、迁移与性能诊断。压缩包共2000个文件,约312.28MB,以…

2026/10/30 14:19:18

1994年DOS实模式TSR卸载源码:热键恢复中断向量与MCB内存回收

简介:这份PDF整理的是雷军早年写下的汇编代码及相关说明,面向对底层编程、DOS历史、内存管理与系统优化感兴趣的开发者和计算机专业学习者。内容围绕一个通过热键卸载后台常驻内存程序的汇编实现展开,涉及当时常见应用与驱动软件的兼容处理&a…

2026/10/30 14:19:18

组网图PPT素材库拆解:PDF矢量提取、绘图参数与母版固化

简介:这份华为内部培训PPT素材库以PDF形式整理,面向网络工程师、售前售后方案人员及培训讲师,用于快速绘制专业组网图、产品架构图与业务说明页,兼顾方案演示和培训课件制作。素材覆盖数据库与立体部件组合、C&C08、iNET、MA …

2026/10/30 14:19:18

Exchange EWS实战:C#邮件同步、会议预约与分页搜索避坑

简介:面向需要使用C#接入微软Exchange邮箱的开发者,这份英文技术文档围绕EWS Managed API展开,适合已具备C#与.NET基础、希望实现邮件处理、日历管理、联系人同步等企业邮箱自动化操作的中级读者。压缩包内仅含1个doc文件,约147KB…

2026/10/30 14:14:16

企业级二级域名分发系统:从源码到生产就绪的完整实践

简介:这是一套面向企业开发者与域名服务提供商的2025二级域名分发系统商业版网站源码,解决多租户场景下子域名快速注册、解析、租赁与统一管理的痛点,适用于云服务平台、虚拟主机商及SaaS应用厂商构建自有域名分发中台。资源共2000个文件&…

2026/10/29 17:05:52

全国计算机二级C语言真题PDF高效刷题指南

简介:这份PDF是全国计算机二级C语言考试的试题与答案解析,专为备考二级C语言的考生准备。内容涵盖C语言特点与设计理念、程序基本组成单位、main函数执行流程、函数嵌套调用规则、标识符命名规范、整型实型字符型数据类型、八进制十六进制数合法形式、运…

2026/10/29 17:06:02

requests+BeautifulSoup:爬虫抓取h1标题的入门实战指南

简介:一份以实战为导向的Python爬虫入门资源,面向具备基本编程基础、希望快速掌握网络数据抓取的初学者,可解决从零编写简单爬虫的常见困惑。实例以requests库发送HTTP请求、BeautifulSoup解析HTML文档,完整演示从网页中提取 标题…

2026/10/29 17:06:13

递推最小二乘参数辨识MATLAB编程:二阶系统与渐消记忆实现

简介:这是一篇面向控制系统、信号处理与机器学习等领域学习者的最小二乘参数辨识程序说明文档。资源共包含一个docx格式文档,压缩包大小七十八KB,内容围绕递推最小二乘算法和渐消记忆最小二乘算法展开:先构造一个极点位于单位圆内…

2026/10/30 0:00:46

NCP1342高频准谐振反激控制器:从设计约束到验收的完整方案

简介:NCP1342 高频准谐振反激控制器应用介绍译文文档,面向电源设计工程师、硬件研发人员及开关电源学习者,帮助读者跨越英文原版资料的语言门槛,系统理解这款高集成度 QR Flyback 控制器的设计要点。文档围绕芯片核心特性展开&…

2026/10/30 0:00:46

NCP1342准谐振反激电源设计:从选型到验收的全流程解析

简介:这份文档面向电源设计工程师与开关电源学习者,系统梳理NCP1342高频准谐振反激控制器的应用要点,帮助读者快速理解这款高集成度离线电源变换器控制芯片的工作机制与设计方法。内容涵盖芯片核心特性、引脚功能定义、电气特性参数表、最大额…

2026/10/30 0:00:46

Web系统自动登出机制设计与实现全解析

1. 系统自动登出机制的设计初衷在各类Web应用和后台管理系统中,自动登出功能早已成为标配。这个看似简单的功能背后,实际上涉及用户安全、资源管理和体验优化的多重考量。作为从业十多年的老开发,我见过太多因为登出逻辑设计不当导致的安全事…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑