使用realloc重新分配内存后,务必,

  使用realloc重新分配内存后,务必,

  Realloc Realallocation内存详解_羽夜水灵_百度空间

  Realloc重新分配内存。最近在写源代码的时候,需要在数组的缓冲时间里重新申请一个缓冲,所以找到了一些资料。乖乖,原来指针还能“漂移”。重新分配

  原型:extern void * realloc(void * mem _ address,unsigned int new size);

  用法:#include stdlib.h有些编译器需要# includealloc.h。

  函数:将mem_address指向的内存区域大小改为newsize长度。

  注意:如果重新分配成功,将返回指向已分配内存的指针;否则,将返回空指针。

  当不再使用内存时,应该使用free()函数来释放内存块。

  注意:此处原始内存中的数据保持不变。

  示例:

  //realloc.c

  #包含syslib.h

  #包含alloc.h

  主()

  {

  char * p;

  clr SCR();//清除屏幕

  p=(char *)malloc(100);

  如果(p)

  printf(内存分配在:%x ,p);

  其他

  printf(内存不足! n’);

  getchar();

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

  如果(p)

  printf(内存重新分配于:%x ,p);

  其他

  printf(内存不足! n’);

  免费(p);

  getchar();

  返回0;

  }

  详细说明和注意事项:

  1.如果有足够的空间来扩展mem_address所指向的内存块,则分配额外的内存并返回mem_address。

  我们这里说的是“扩张”。我们知道,realloc从堆中分配内存。当扩展内存空间时,realloc()尝试直接从堆上现有数据后面的那些字节中获取额外的字节。如果能满足,一切都会好的。也就是说,如果在原始内存大小之后还有足够的空闲空间可以分配,则加上原始空间大小=新大小。那好吧。你得到的是一个连续的记忆。

  2.如果原始内存大小后面没有足够的空闲空间用于分配,那么从堆中找到新大小的另一个内存。

  并将原始内存空间的内容复制到newsize中。返回新的mem_address指针。(数据已被移动)。

  旧木块被放回了木堆上。

  例如:

  #包含malloc.h

  char *p,* q;

  p=(char *)malloc(10);

  q=p;

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

  …………………………

  这个程序可能在编译器里通不过,因为编译器可能会为我们消除一些隐患!这里我们只是加了一个指针Q记录原内存地址,然后记录原内存地址p,如果数据不幸被移动了,那么记录的原内存地址Q所指向的内存空间其实已经被放回堆里了!这样我们才应该最终意识到问题出在哪里,有多可怕!

  3.返回情况

  返回的是void类型的指针,调用成功。(这个会在你需要的时候施放)

  返回NULL。当要扩展的大小(第二个参数)为0且第一个参数不为NULL时,原始内存被“释放”。

  返回NULL。当没有足够的扩展空间时,原始内存空间的大小保持不变。

  4.特殊情况

  如果mem_address为null,那么realloc()和malloc()类似。分配一个新的内存块,并返回一个指向该内存块的指针。

  如果newsize的大小为0,则释放mem_address所指向的内存,并返回null。

  如果没有足够的可用内存来完成重新分配(扩展原始内存块或分配新的内存块),则返回null。原始内存块保持不变。

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

  void* malloc(无符号大小);void* calloc(size_t nelem,size _ t elsize);以及void * realloc (void * ptr,无符号新大小);都在stdlib.h函数库里,这是C语言的标准内存分配函数。

  1.malloc()和calloc()函数都可以用来动态分配内存空间。malloc()函数有一个参数,即要分配的内存空间的大小。malloc在分配内存时会保留一定的空间来记录分配情况。分配的次数越多,这些记录占用的空间就越大。此外,根据不同的malloc实现策略,malloc每次分配的空间都可能超过实际需求,多次分配会导致更多这样的浪费。当然,这些都与malloc的实现有关;calloc()函数有两个参数,即元素的数量和每个元素的大小。这两个参数的乘积就是要分配的内存空间的大小。如果调用成功,它们都将返回分配的内存空间的第一个地址。

  2.malloc()和calloc()的主要区别在于,前者不能初始化分配的内存空间,而后者可以。

  3.realloc可以扩展或收缩给定指针指向的空间。无论是扩展还是收缩,原内存的内容都保持不变。当然,对于还原,还原部分的内容会丢失。

  4.realloc不保证调整后的内存空间和原始内存空间保持相同的内存地址。相反,realloc返回的指针很可能指向一个新地址。所以在代码中,我们必须将realloc返回的值重新赋值给p:

  p=(int *) realloc (p,sizeof(int)* 15);

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

  真正了解realloc的工作原理。发表于2008-11-20 13:12夏季阅读(142)评论(0)编辑收藏网摘要类别:c/c

  Realloc已经用过很多次了。无非是扩大一个已有的记忆。

  char * p=malloc(1024);

  char* q=realloc(p,2048);

  现在的问题是指针p应该怎么处理,一开始按照我最直观的理解,如果是直接设置p=NULL。最后我们只需要释放q的空间。

  因为我最近在做一个包。结果在单元测试的时候发现了。有时候我是自由的(q);会出问题的。这让我很郁闷。

  仔细跟踪,发现realloc之后Q和P的指针地址是一样的。但有时候不一样。

  我仔细检查了信息。获取以下信息:

  1.如果当前的连续内存块足够realloc使用,只需扩展P指向的空间,返回P的指针地址,此时Q和P指向同一个地址。

  2.如果当前的连续内存块不够长,再找一个足够长的地方,分配一个新的内存Q,将P指向的内容复制到Q,返回Q,P指向的内存空间被删除。

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

  这里,重要的是避免p=realloc(p,2048);这种写作方式。在realloc分配失败后,它可能会导致p最初指向的内存地址丢失。

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

  对realloc函数描述的补充:

  函数定义:

  void *realloc(void *ptr,size _ t size);

  以上分析基本没有问题,但有两点需要注意:

  1.返回值可能不同于ptr的值。如果是,那么在realloc函数完成后,ptr指向的旧内存已经被释放。

  2。如果返回NULL值,则分配不成功,并且原始ptr指向的内存还没有释放,因此要求程序显式释放。

  因此,p=(int *) realloc (p,sizeof(int)* 15);语句有这样一个问题,

  在调用p之前,它指向一个已经分配成功的内存,但是在调用realloc时,它失败了(即返回NULL)。这时,p原本指向的内存还没有被释放,现在找不到地址,于是出现了内存泄漏。

  注意这一点真的很重要。最好如下:

  int *q

  q=(int *) realloc (p,sizeof(int)* 15);

  如果(!q)p=q;

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

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

  #包含malloc.h

  char * p;

  p=(char *)malloc(10);

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

  …………………………

  这个程序的意思很简单,只有有点C基础的人才能看懂。该函数首先定义一个字符指针P,然后为指针P分配一个10字节的内存空间,然后将这个内存块的大小增加到20字节。

  这里有问题吗?在电脑上运行一下,好像没什么问题!

  是的,这样在电脑上运行是没有问题的,但是存在着我们可能不太注意的隐患!隐患在哪里?这就是我想在本文中详细解释的realloc()函数。

  看看下面这段来自MSDN的话:

  realloc返回一个空指针,指向重新分配(也可能被移动)的内存块。如果大小为零且缓冲区参数不为NULL,或者没有足够的可用内存将块扩展到给定的大小,则返回值为NULL。在第一种情况下,原始块被释放。在第二种情况下,原始块保持不变。返回值指向一个存储空间,该空间保证为存储任何类型的对象而适当对齐,若要获取指向除void之外的类型的指针,请对返回值使用类型转换。

  E的这一段不晦涩,就不翻译了。大致意思是关于realloc的返回值。但是这里有几种关于他的返回值的情况:

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

  2.返回NULL。当要扩展的大小(第二个参数)为0且第一个参数不为NULL时,原始内存被“释放”。

  3.返回NULL。当没有足够的空间进行扩展时,此时,原始内存空间的大小保持不变。

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

  第二种情况可能只有傻子才会用!

  第三种情况,内存空间不足时,未来大小不变。

  MSDN说,当没有足够的内存空间时,原来的内存空间将不会扩大。这个说法没有错,但是有点模糊,好像漏了一个情况!我们知道,realloc从堆中分配内存。当扩展内存空间时,realloc()尝试直接从堆上现有数据后面的那些字节中获取额外的字节。如果能满足,一切都会好的。但是如果数据后面没有足够的字节,问题就出现了。然后,将使用堆上第一个具有足够大小的空闲块,然后将现有数据复制到新位置,并将旧块放回堆中。这句话的一个重要信息是,数据可能会被移动!看到这里,也许我们已经发现了我一开始给出的程序的问题。为了更清楚地解释问题,您可以将上面的程序更改为以下形式:

  #包含malloc.h

  char *p,* q;

  p=(char *)malloc(10);

  q=p;

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

  …………………………

  这个程序可能在编译器里通不过,因为编译器可能会为我们消除一些隐患!这里我们只是加了一个指针Q记录原内存地址,然后记录原内存地址p,如果数据不幸被移动了,那么记录的原内存地址Q所指向的内存空间其实已经被放回堆里了!这样我们才应该最终意识到问题出在哪里,有多可怕!

  这个问题看起来有点死路一条,因为我们可能永远也不会遇到,但是我们要明白,这样的事情总是存在的。只有这样,我们才能有意识地避免这种隐患,以防万一。否则一旦出现这样的隐患,程序崩溃,恐怕查错也不是一件容易的事情!

  侯在《深入浅出MFC》中引用了林语堂《朱门》中的一句话,我深有感触。虽然不可能有他的深情,但我抱着向前辈学习的心态,所以也把它作为本书的结尾:

  “只用一个东西而不明白他的道理,真的不聪明”。

使用realloc重新分配内存后,务必,