首页 > 其他 > 详细

【摘要】malloc、calloc和realloc的用法

时间:2019-06-25 11:30:40      阅读:94      评论:0      收藏:0      [点我收藏+]

realloc 用过很多次了。无非就是将已经存在的一块内存扩大。

char* p = malloc(1024);
char* q = realloc(p,2048);

现在的问题是我们应该如何处理指针 p。 刚开始按照我最直观的理解,如果就是直接将 p = NULL;。 到最后只需要释放 q的空间就可以了。

因为最近在做个封装。结果在做单元测试的时候发现。有时候我在 free(q); 的时候会出错。这样我就郁闷了。

后来仔细一跟踪,发现 realloc 完以后 q 和 p 的指针地址是一样。不过有时候又不一样。

仔细查了下资料。得到如下信息:

       1.如果 当前连续内存块足够 realloc 的话,只是将p所指向的空间扩大,并返回p的指针地址。 这个时候 q 和 p 指向的地址是一样的。

       2.如果 当前连续内存块不够长度,再找一个足够长的地方,分配一块新的内存,q,并将 p指向的内容 copy到 q,返回 q。并将p所指向的内存空间删除。

这样也就是说 realloc 有时候会产生一个新的内存地址 有的时候不会。所以在分配完成后。我们需要判断下 p 是否等于 q。并做相应的处理。

这里有点要注意的是要避免 p = realloc(p,2048); 这种写法。有可能会造成 realloc 分配失败后,p原先所指向的内存地址丢失。

 

=========================================

关于realloc函数说明的补充:
函数定义:
void *realloc(void *ptr, size_t size);
上面的分析基本没有问题,但有两点要注意:
1.返回值可能与ptr的值不同,如果是不同的话,那么realloc函数完成后,ptr指向的旧内存已被free掉了。
2。如果返回NULL值,则分配不成功,而原来的ptr指向的内存还没有被free掉,要求程序显式free.

故p = (int *) realloc (p, sizeof(int) *15);语句有这么一个问题,
调用前p指向一个已分配成功的内存,而调用realloc时却失败(即返回NULL),此时,p原来指向的内存还没有free掉,而现在又找不到地址,这样就出现memory leak了。

关于这一点的确要注意,最好如下:
int *q
q = (int *) realloc (p, sizeof(int) *15);

if(!q) p =q;

 

======================================================

 

首先看一下下面的C程序片断:

 

#include <malloc.h>

char  *p;

p = (char * ) malloc (10);

p = (char * ) realloc (p,20);

…………………………

返回值分了几种情况:

1、  返回void * 指针,调用成功。

2、  返回NULL,当需要扩展的大小(第二个参数)为0并且第一个参数不为NULL,此时原内存变成了“freed(游离)”的了。

3、  返回NULL,当没有足够的空间可供扩展的时候,此时,原内存空间的大小维持不变。

 

第一种情况告诉了我们在得到需要的内存空间后需要做类型转换的工作;

第二种情况可能只有傻瓜才会去使用吧!

第三种情况,内存空间不够的时候就会维持未来的大小不变。

 

        MSDN上面说内存空间不够的时候就不会扩展原来的内存空间的大小,这话固然没有错,但是有点含糊,似乎遗漏了一种情况!我们知道,realloc是从堆上分配内存的,当扩大一块内存空间时, realloc()试图直接从堆上现存的数据后面的那些字节中获得附加的字节,如果能够满足,自然天下太平;可如果数据后面的字节不够的话,问题就出来了,那么就使用堆上第一个有足够大小的自由块,现存的数据然后就被拷贝至新的位置,而老块则放回到堆上。这句话传递的一个重要的信息就是数据可能被移动!看到这里,也许我们已经发现一开始我给出的程序的问题了。为了更清楚地说明问题,可以将上面的程序改成下面的形式:

 

#include <malloc.h>

char  *p,*q;

p = (char * ) malloc (10);

q=p;

p = (char * ) realloc (p,20);

…………………………

    这段程序也许在编译器中没有办法通过,因为编译器可能会为我们消除一些隐患!在这里我们只是增加了一个记录原来内存地址的指针q,然后记录了原来的内存地址p,如果不幸的话,数据发生了移动,那么所记录的原来的内存地址q所指向的内存空间实际上已经放回到堆上了!这样一来,我们应该终于意识到问题的所在和可怕了吧!

    这个问题似乎有点牛角尖的味道,因为我们也许从来不曾遇上过,但是我们应该明白这样的事情的始终存在,只有这样,在万一我们碰上的时候才会去有意识的去避免这种隐患,否则,一旦这样的隐患一旦发作,程序崩溃不说,恐怕查错也不是一件容易的事!

 

【摘要】malloc、calloc和realloc的用法

原文:https://www.cnblogs.com/cy1993/p/11081295.html

(0)
(0)
   
举报
评论 一句话评论(0
分享档案
最新文章
教程昨日排行
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!