关于内存分配函数realloc()的思考

转自: 点击打开链接
这个问题有一个程序开始讲起:
Status Push (SqStack &s, SElemType a)
{
         // 插入元素 a 为新的栈顶元素
         if (S.top – S.base>=S.stacksize) // 栈满,追加存储空间
         {
                   S.base = (SElemType *) realloc( S.base,(S.stacksize+STACKINCREMENT)*sizeof(SElemType));
                   if (!S.base) exit(OVERFLOW); // 存储空间分配失败
                   S.top=S.base+S.stacksize;//因为用realloc时,基地址变了,所以栈顶指针也要跟着改变。但realloc会把原来的数据都搬到新的基地址上,只要新申请的空间比
                                                                   //原数据大,就不会丢失。
                   S.stacksize+=STACKINCREMENT;
         }
         *S.top++=a;
         return OK;
} //Push.
这段代码出自于《数据结构》(严蔚敏 吴伟民)第47页。函数的只要功能实现元素压栈,如果栈的空间不足够的时候利用realloc()函数进行再新分配空间,使得函数得以实现。
我们注意里边的一句代码:
S.top=S.base+S.stacksize;
在再分配空间之前,S.top指向栈的顶部。

而这句代码有是什么意思呢?S.top=S.base*S.stacksize同样是指向栈的顶部元素。这是不是多此一举呢?
我们看 realloc() 函数的一些说明。

语句 :
realloc (ptr, size)
 
参数 :
ptr is a null pointer or a pointer previously returned by calloc or malloc or realloc function, size is an integer representing the number of byes to be allocated.
 
返回值 :
A pointer to the possibly moved allocated memory, if any.  Returns null otherwise
资料来自: http://www.picsupport.com/ccsc/REALLOC.htm
由这些资料我们可以看出,函数realloc()在使用的过程中,可能改变prt的值。如果要开辟的内存在原来的空间上不能够实现的时候,函数将在另外的地方开辟新的空间,复制数据,把原来的内存空间释放(free())返回新的内存地址。问题就是在这里了,回到我们原来的程序,如果在追加空间的时候改变了指针S.base的值,那么必须保证S.top也作响应的改变。
语句S.top=S.base+S.stacksize;保证了整个程序的安全性。

这里不能用malloc函数追加数组空间。因为malloc函数是这样的:
malloc操作系统申请空余内存的“堆”存储空间,然后把申请到的首地址返回。
若栈已满,执行到这条语句
S.base=(SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));
则S.base指向新申请到的内存地址,原base地址丢失。
也就是说,你通过malloc函数申请的空间是操作系统分配的,不能通过指定起始地址来分配。
应该用realloc函数,此函数原型:
 void *realloc(void *mem_address, unsigned int newsize); 
语法:指针名=(数据类型*)realloc(要改变内存大小的指针名,新的大小)。
注意:新的大小一定要大于原来的大小不然的话会导致数据丢失!
此函数功能:先按照newsize指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来mem_address所指内存区域,同时返回新分配的内存区域的首地址。即重新分配存储器块的地址。

为了验证realloc()函数有可能改变指针地址,我们看下面的代码。
#include<string.h>
#include<malloc.h>
main()
{
       char *p,*q;
        p = (char *)malloc(10);
    strcpy(p,"abcdefghi/0");
    printf("%d/n",p);               //第一次malloc后p所指向的空间
    q = p;
    p = (char * )realloc(p,8521);
printf("%d     %s/n",p,p);
 //可以观察realloc后p指向的地址同malloc后所指向的地址是否发生
            //了变化,如果没有变化就把realloc中的第二个参数再变大一些!
         free(q);   //当p值得发生改变的时候,该语句将会发生错误,程序出错。因为q指向                                 //的空间已经被realloc()函数释放,
       if(p==q)
              printf("p==q");
       else
              printf("p!=q");
       printf("/n %s",q);
       printf("/n %s",p);
}
在该段程序中,如果把语句free()注释掉,我们还可以看到:语句printf("/n %s",q);和printf("/n %s",p);打印的值得还是一样的,说明realloc()的释放空间功能并没有将数据删除,只是告诉编译器没在被分配的状态下。事实上,关于free()函数,有如下的说明:
The free function causes the space pointed to by the ptr to be deallocated, that is made available for further allocation. If ptr is a null pointer, no action occurs. If the ptr does not match a pointer earlier returned by the calloc, malloc or realloc, or if the space has been deallocated by a call to free or realloc function, the behavior is undefined.
资料来自:http://www.picsupport.com/ccsc/FREE.htm
显然我们可以了解到,为什么当p的值发生改变时,使得free(q)语句出错,同时更清楚知道free()函数的本质。
-------------------------------------------------------------------------------------------------------------------
 
说明:本文的写作参考了一写网上资料,提供上网址:
http://www.picsupport.com/ccsc/FREE.htm     关于free(prt)函数的使用
http://www.picsupport.com/ccsc/REALLOC.htm    realloc(prt,size)的使用。
http://dev.csdn.net/article/27/27950.shtm  内存分配——realloc()函数的使用
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值