2

众所周知,realloc() 的作用就是将已经 malloc 的内存块,重新扩展加长。当你并没有使用高端的内存池的时候,临时从堆中申请加大内存,这是很有用的。但是如何正确地使用 realloc() 呢?

Reference

realloc 用法

调用方法

函数原型

#include <stdlib.h>

void *realloc(void *ptr, size_t size);

传入参数:
(1)需要被扩展大小的内存指针
(2)扩展后的大小(注意不是添加的大小)

返回参数:
  新的指针


正确的调用方式

长篇大论放后面,我们先上代码:

uint8_t *pMemToBeRealloc = malloc(1024);
size_t memSize = 1024;
...

/* start realloc */
uint8_t *pMemBackup = pMemToBeRealloc;    /* 将 realloc 之前的内存地址备份一下 */
pMemToBeRealloc = realloc(pMemToBeRealloc, 2048);

if (pMemToBeRealloc) {                    /* realloc 成功 */
    LOG_DEBUG("Memory had been extent to 2048.");
    pMemBackup = NULL;
    memSize = 2048;
}
else {                                    /* realloc 失败了,这个时候返回的是 NULL */
    LOG_ERROR("Oh no, realloc() failed: %s.", strerror(errno));
    pMemToBeRealloc = pMemBackup;
    memSize = 1024;
}

...

原理

realloc() 返回 NULL 的时候,表示内存扩展动作失败了。但这个时候,原来的内存并没有被释放,所以有必要把原来的内存预先备份下来。至于失败的时候要怎么处理,那就是程序员自己的事情了,这没有标准方案。

realloc() 返回非零值时呢,表示realloc是成功的。此时不论返回值是多少,程序都不需要对原来的内存地址值作特殊操作

为什么这么说呢?主要是参考资料里面没有把一个问题说清楚:

  1. 首先,如果 pMemToBeRealloc == pMemBackup的情况,那说明只是在原来的内存基础上往后扩展就好了,这是最简单的情况
  2. 可是如果 pMemToBeRealloc != pMemBackup 呢?这很容易让人误解为,需要调用一次 free(pMemBackup)。这是错误的,因为这个动作,realloc 会自动帮你做了,不要画蛇添足!

BTW,个人还建议注意一个地方:从 man 手册上面看,虽然对于 malloc() 返回的内存,大部分标准库会初始化为全零,但是对于 realloc() 扩展的部分,则不一定。
不过保险起见,应该是对于 malloc() 和 realloc() 返回的内存内容,都不要相信它们都已经被初始化为0才好。


amc
927 声望228 粉丝

电子和互联网深耕多年,拥有丰富的嵌入式和服务器开发经验。现负责腾讯心悦俱乐部后台开发