代码质量与安全

realloc 为什么可能造成内存泄漏?从返回值到所有权检查

realloc 为什么可能造成内存泄漏?从返回值到所有权检查

realloc 可能导致内存泄漏,常见原因是直接用返回值覆盖唯一的原指针:当非零大小的重新分配失败时,旧内存仍需管理,而原指针已经丢失。另一个风险出现在成功移动之后:指向旧块或块内位置的指针不能继续照旧使用。

先明确讨论的是哪个接口

下面讨论普通 C `realloc` 的非零大小请求:分配失败时,旧对象不释放。实际工程还可能使用封装函数或宏,它们的失败条件、分配器和零大小行为需要单独核对。C 标准工作组相关说明

例如,Python C API 为 `PyMem_Realloc` 说明了自己的零大小处理方式。不能因为名字相近,就把某一版本的 Python 宏定义等同于所有平台的 `realloc`。Python 内存管理文档

使用临时指针处理成功和失败

以下为独立的教学示例。约定 `*buffer` 是可由 `realloc` 调整的有效内存或空指针,`new_size` 必须大于零;失败时由调用者继续持有原内存。

```c #include <stddef.h> #include <stdlib.h>

realloc 为什么可能造成内存泄漏?从返回值到所有权检查相关图片1

int resize_buffer(char **buffer, size_t new_size) { if (buffer == NULL || new_size == 0) { return -1; } char *temporary = realloc(*buffer, new_size); if (temporary == NULL) { return -1; /* 原内存仍归调用者管理 */ } *buffer = temporary; return 0; } ```

这个函数保留了失败时的所有权。调用者仍需决定继续使用旧缓冲区,还是执行清理并终止操作;返回错误本身不代表资源已经释放。

成功路径也可能有问题

如果另一个变量记录了块内位置,调整前应保存合法偏移,成功后基于新地址重新计算。缩小缓冲区时,还要确认偏移和后续访问仍在新边界内。不要以某次地址恰好未变为依据继续依赖旧指针。

若新大小来自“元素数 × 单个元素大小”,应在调用前检查整数溢出。零大小请求则单独定义行为,例如由业务显式释放并置空,避免依赖不同标准或实现间的差异。

静态告警怎样复核

沿路径检查原始分配、所有权转移、返回值覆盖及所有退出分支,再展开实际使用的封装或宏。要判断一个具体项目是否真的泄漏,还需要版本、源码位置和可达条件;工具截图不足以代替这些证据。

缩小内存就一定成功吗? 不能作此假设,仍需处理返回值。

realloc 为什么可能造成内存泄漏?从返回值到所有权检查相关图片2

用了临时指针就完全安全了吗? 还需检查大小计算、旧别名、所有权和最终释放。示例只解决失败时丢失唯一原指针这一类问题。

返回观点列表