C 语言 realloc 函数
外观
realloc函数概述[编辑 | 编辑源代码]
realloc(全称re-allocation)是C标准库(<stdlib.h>)中用于动态调整已分配内存块大小的函数。它解决了以下核心问题:
- 当程序运行时发现原先分配的内存不足时,无需手动创建新内存块并复制数据
- 当分配的内存过大时,可以缩小内存块以减少内存占用
函数原型[编辑 | 编辑源代码]
void *realloc(void *ptr, size_t size);
- ptr:指向先前由malloc/calloc/realloc分配的内存块的指针
- size:内存块的新大小(字节数)
- 返回值:指向重新分配内存块的指针(可能与ptr不同)
工作原理[编辑 | 编辑源代码]
关键行为说明: 1. 原地扩展:当原内存块后续的地址空间未被占用时,直接扩大分配 2. 迁移扩展:当无法原地扩展时,自动完成:
* 分配新内存块 * 复制原数据(仅复制到min(旧大小,新大小)) * 释放原内存块
3. 缩小内存:可能释放多余内存,但实现依赖具体编译器
使用示例[编辑 | 编辑源代码]
基础示例[编辑 | 编辑源代码]
#include <stdio.h>
#include <stdlib.h>
int main() {
// 初始分配10个int的空间
int *arr = (int*)malloc(10 * sizeof(int));
// 检查分配是否成功
if(arr == NULL) {
printf("内存分配失败!\n");
return 1;
}
// 使用内存(示例填充数据)
for(int i=0; i<10; i++) arr[i] = i;
// 需要更多空间,扩展到20个int
int *new_arr = (int*)realloc(arr, 20 * sizeof(int));
if(new_arr == NULL) {
printf("内存重新分配失败!\n");
free(arr); // 原始指针仍需释放
return 1;
}
arr = new_arr; // 更新指针
// 使用新增的空间
for(int i=10; i<20; i++) arr[i] = i;
// 打印结果(部分示例)
printf("扩展后数组[15]: %d\n", arr[15]);
free(arr); // 最终释放
return 0;
}
输出示例:
扩展后数组[15]: 15
错误处理模式[编辑 | 编辑源代码]
正确使用realloc应遵循以下模式:
void *tmp = realloc(ptr, new_size);
if (tmp == NULL) {
// 处理错误,原ptr仍然有效
// 可能需要执行清理操作
} else {
ptr = tmp; // 只有成功时才覆盖原指针
}
进阶注意事项[编辑 | 编辑源代码]
性能考量[编辑 | 编辑源代码]
realloc可能触发内存复制操作,时间复杂度为O(n)。对于大型内存块:
- 频繁调整大小会导致性能下降
- 推荐策略:采用指数级增长(如每次扩大为原大小的1.5-2倍)
数学表达式:
特殊边界情况[编辑 | 编辑源代码]
情况 | 行为 | 等效操作 |
---|---|---|
ptr为NULL | 等同于malloc(size) | malloc(size) |
size为0 | 释放内存块 | free(ptr) |
ptr未指向动态内存 | 未定义行为 | - |
实际应用案例[编辑 | 编辑源代码]
动态数组实现[编辑 | 编辑源代码]
以下展示如何用realloc实现动态数组的自动扩容:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int *data;
size_t size;
size_t capacity;
} DynamicArray;
void push_back(DynamicArray *da, int value) {
if (da->size >= da->capacity) {
// 容量不足时扩容(初始容量为1的情况)
size_t new_capacity = da->capacity == 0 ? 1 : da->capacity * 2;
int *new_data = realloc(da->data, new_capacity * sizeof(int));
if (!new_data) {
printf("扩容失败!\n");
return;
}
da->data = new_data;
da->capacity = new_capacity;
}
da->data[da->size++] = value;
}
内存池优化[编辑 | 编辑源代码]
在游戏开发等性能敏感场景中,可采用「预分配+realloc」策略: 1. 初始化时分配预估内存 2. 运行时根据实际需求精细调整 3. 避免频繁调用malloc/free
常见问题[编辑 | 编辑源代码]
页面模块:Message box/ambox.css没有内容。
错误示例:直接覆盖原指针 |
ptr = realloc(ptr, new_size); // 若失败会导致内存泄漏
页面模块:Message box/ambox.css没有内容。
错误示例:忽略返回值检查 |
realloc(ptr, new_size); // 未处理可能失败的情况
最佳实践总结[编辑 | 编辑源代码]
- 总是检查返回值
- 使用临时指针接收结果
- 考虑内存对齐的影响(某些系统对realloc有特殊对齐要求)
- 对于多线程环境,需要同步机制保护realloc操作
扩展阅读[编辑 | 编辑源代码]
- 内存碎片化与realloc的关系
- 对比C++的vector.resize()实现
- 各标准库实现差异(glibc vs musl等)