首页 > 精选问答 >

问 realloc 函数使用规则 C 语言内存重分配详解

2026-11-11 17:40:59
最佳答案

答

realloc 是 C 语言标准库 stdlib.h 里面的内存重分配函数,核心作用是对已经通过 malloc calloc 申请成功的堆内存,调整它的大小,可以扩大也可以缩小,函数原型是 void realloc (void ptr, size t size),第一个参数是原有堆内存指针,第二个参数是想要调整之后的新总字节数,很多新手最容易踩坑的点就是 realloc 执行之后,原指针有可能失效,函数会返回一个新的内存起始地址,如果直接把返回值赋值回原指针,一旦分配失败原指针就丢失,造成内存泄漏,同时 realloc 只能作用在堆内存,不能作用在栈内存,也不能处理已经 free 释放过的指针,这个是使用规则里面最核心的硬性要求,理解它的内部逻辑,系统会优先尝试在原内存块后面扩展空间,如果后面空闲空间足够,返回的还是原来的旧地址,如果后面空间不够,系统会重新开辟一块新的足够大内存,把旧内存里面原有数据拷贝到新内存,然后自动释放旧内存块,最后返回新地址,这个机制就是为什么指针可能发生移动。

之所以要掌握 realloc 这套规则,是因为动态数组是 C 语言非常常用的写法,当数组元素不断增加,提前申请的内存不够用的时候,就需要 realloc 扩容,相比每次重新 malloc 然后手动拷贝旧数据,realloc 已经帮我们封装了拷贝和释放旧块的逻辑,但是它的返回值特性很特殊,和 malloc calloc 不一样,很多人没有理解返回值的含义,写出存在隐患的代码,出现野指针 内存泄漏 程序崩溃这类问题,而且 realloc 缩小内存的时候,只会保留前面部分的数据,超出新 size 后面的数据会直接丢弃,这个细节很多教材不会重点强调,写业务代码的时候很容易忽略。

核心参数与返回值对照表

项目详细说明
头文件stdlib.h
函数原型void realloc(void ptr, size t size)
第一个参数 ptr已经由 malloc calloc realloc 申请的堆指针
第二个参数 size调整之后整块内存的总字节数,不是新增字节
成功返回新内存块起始地址,有可能等于旧地址,也有可能是新地址
失败返回NULL,原有旧内存不会被释放,里面数据保持不变
特殊情况ptr 传 NULL,等价于 malloc size
特殊情况size 传 0,等价于 free ptr,部分编译器行为存在差异

分层详细使用要点

第一 合法输入前提,ptr 必须是堆上动态申请的指针,栈数组地址 全局静态内存地址 已经 free 的指针,传给 realloc 属于未定义行为,程序会崩溃。

第二 扩容核心陷阱,不能写成 ptr = realloc (ptr, newSize),如果 realloc 分配失败返回 NULL,原来的 ptr 就被覆盖成 NULL,旧内存块地址直接丢失,再也无法 free,造成内存泄漏,标准安全写法是定义临时指针接收返回值,判断临时指针不为空之后,再赋值给原指针。

第三 size 是总大小,不是追加增加的字节数,比如原来申请 100 字节,想扩容到 200 字节,第二个参数直接写 200,不是写 100,这是高频逻辑错误。

第四 数据保留规则,扩容的时候原有全部数据会自动拷贝保留,缩小内存的时候,只保留前 size 字节的数据,后面多余的数据直接丢弃。

第五 内存释放,realloc 成功之后旧内存块会被系统自动释放,不需要手动再 free 原来的旧指针,但是最终这块新内存不再使用的时候,依然要调用 free 释放。

第六 线程与并发,realloc 不是线程安全函数,多线程同时操作同一个内存块,需要加锁保护。

标准安全编码步骤

第一步 提前使用 malloc 或者 calloc 申请初始堆内存,保存好指针。

第二步 当内存容量不足,准备扩容,定义临时指针,比如 void temp = realloc (oldPtr, newTotalSize)。

第三步 判断 temp 是否等于 NULL,如果等于 NULL,代表扩容失败,保留 oldPtr,做错误处理,不要覆盖原指针。

第四步 如果 temp 不为空,代表扩容成功,把 oldPtr 赋值成 temp,后续代码使用新指针。

第五步 程序结束不再使用这块内存,调用 free 释放最终的指针。

综合来说 realloc 函数使用规则重点就是三点,只允许处理堆动态内存,size 填写总字节数,必须用临时指针接收返回值做判空,理解原地址可能迁移这个底层机制,就能避开绝大多数经典 bug,它适合动态数组 动态缓冲区这类需要动态调整内存大小的场景。

【常见问题】

问题 1 realloc 函数使用规则里面为什么不能直接 ptr = realloc (ptr,size)

回答 1 realloc 函数使用规则里,直接 ptr = realloc (ptr,size) 有风险,realloc 函数使用规则规定分配失败返回 NULL,这种写法会覆盖原指针,造成旧内存泄漏,realloc 函数使用规则推荐临时指针接收返回值再判断。

问题 2 realloc 函数使用规则可以传入栈内存指针吗

回答 1 realloc 函数使用规则明确不可以传入栈内存指针,realloc 函数使用规则要求 ptr 必须是 malloc calloc 申请的堆内存,传入栈指针属于未定义行为。

问题 3 realloc 函数使用规则第二个参数是新增字节吗

回答 1 realloc 函数使用规则里第二个参数不是新增字节,realloc 函数使用规则要求填写调整之后整块内存的总字节数,很多新手在这里写错参数。

【免责申明】

本内容为 realloc 函数使用规则 C 语言通用讲解,不同编译器对 size 为 0 等边界行为实现存在细微差异,内容仅作为编程学习参考,实际开发请参考对应编译器官方文档与 C 标准规范。