周立功教授数年之心血之作《程序设计与数据结构》,书本内容公开后,在电子行业掀起一片学习热潮。经周立功教授授权,本公众号特对本书内容进行连载,愿共勉之。
第一章为程序设计基础,本文为1.9.3 free()函数和1.9.4 realloc()函数。
>>>>1.9.3free()函数
对于程序而言,不可再访问的内存块被称为垃圾,留有垃圾的程序存在内存泄漏现象。虽然一些语言提供了垃圾收集器用于垃圾的自动定位和回收,但c语言不提供。要求每个程序负责回收各自的垃圾,方法是调用free()函数释放不需要的内存。
通常malloc()要与free()配套使用,当动态内存使用完毕时,如果不及时释放的话,必然导致“内存泄露(即内存空间减少)”,进而影响程序的正常运行。释放内存的free()函数原型如下:
void free(void *pointer);
即将malloc()返回的指针pointer作为参数传给free()释放内存。虽然free()函数允许收回不再需要的内存,但使用此函数会导致一个新的问题:悬空指针。虽然调用free(pi)函数会释放pi,但不会改变pi本身。如果忘记了pi不再指向有效内存块,那么混乱就有可能随即而来:
char *pi = malloc(5);
free(pi);
strcpy(pi, abc);// 错误
即修改了pi指向的内存是严重的错误,因为程序对此内存失去了控制权。事实上,悬空指针是很难发现的,因为几个指针可能指向相同的内存块,在释放内存块后,全部的指针都悬空了。有了free()函数,也可以用malloc()在运行时分配一块连续的内存空间,达到改变数组大小的目的。比如:
char * pi = malloc(5);
即变量pi指向已经在堆内分配的5个连续字节,好像声明了一个有5个字符的数组一样,显然动态数组就是分配在“堆”上,用指针变量引用的数组。分配动态数组的步骤如下:
● 声明一个指针变量用于保存数组变量首元素的地址;
●调用malloc()为数组变量中的元素分配内存
●将malloc()的结果赋给指针变量。
由于不同的数据类型占用的内存大小不一样,其大小为数组变量元素个数乘以每个元素所占内存的大小。比如,有5个int型元素的数组变量需要分配内存。比如:
int *pi = malloc(5 * sizeof(int));
和数组不同的是,当不再使用时,必须释放内存。比如:
free(pi);
如果需要10个元素才够用,那么应该先释放原内存,然后再申请新内存。比如:
free(pi);
pi = malloc(10 * sizeof(int));
显然,存放在原内存的数据不见了,为了保留原来的数据,需要再做些工作:
int *temp = pi; //让temp指向原内存
pi = malloc(10 * sizeof(int)); //让pi指向新内存
memcpy(pi, temp, 5 * sizeof(int));//将原内存的数据拷贝到新内存
free(temp); //释放原内存
但上面的工作仅需一条语句即可完成,比如:
pi = realloc(pi, 10*sizeof(int));
由于free函数不会检查传入的指针是否为null,也不会在返回前将指针设置为null,因此程序员会创建自己的free函数,saferfree函数的接口和实现详见程序清单 1.49和程序清单 1.50。
程序清单1.49saferfree()函数的接口(saferfree.h)
1 #pragma once
2 void saferfree(void **pp);
程序清单1.50saferfreeh函数接口的实现(saferfree.c)
1 #include
2 #include
3
4 void saferfree(void **pp)
5 {
6 if(pp != null && *pp != null)
7 free(*pp);
8 *pp = null;
9 }
10 }
如果使用saferfree宏调用saferfree函数,则可以省略类型转换和传递指针的地址。即:
#define newsaferfree(p) saferfree((void **)&p)
其调用形式如下:
int *pi = malloc(sizeof(int));
newsaferfree(pi);
>>>1.9.4realloc()函数
alloc是allocate分配的缩写,前缀re就是重新分配的意思。如果原内存后面还有剩余的话,realloc()只是修改分配表,还是返回原内存的地址;如果没有剩余内存的话,realloc()将申请新的内存,然后将原内存的数据拷贝到新内存中,原内存将被free()释放掉,realloc()返回新内存的地址。realloc()函数原型如下:
void *realloc(void *pointer, unsigned int size);
当调用realloc()函数时,point必须指向先前通过malloc、calloc或realloc的调用获得的内存块。size表示新分配内存的大小,以字节为单位。其作用是将pointer所指向的动态空间的大小改变为size,pointer的值不变。如果重新分配不成功,则返回null;如果通过malloc()已经获得了动态空间,又不想改变其大小,则可以使用realloc()重新分配。
Ubuntu或在2014年推移动系统,兼容Android是出路?
让协作更便捷,图漾3D工业相机获UR+认证
中国汽车芯片产业面临四大挑战
数据库数据恢复-数据库文件被删除/分区被格式化的SQL SERVER数据恢复方案
虹科分享 | 网络流量监控 | 构建大型捕获文件(Ⅱ)——Pcap分析仪:Allegro网络万用表的Pcap过滤器
周立功“程序设计与数据结构”:深度解剖动态分布内存的free()函数与realloc()函数
基于MSP430F5438A的SPI通信来进行SD卡初始化
工控系统智能化促进工业4.0的到来
高温电路的设计注意事项和元器件的使用技巧
5G的到来,为全球港口产业升级带来了新的机会
小米8即将亮相 同样的配置将小米MIX 2S置于何地?
基于MAX2120卫星调谐器IC的Half-NIM DVB-S调谐器
中国移动将建设世界规模最大的5G试验网
笔记本电脑散热器制作教程
风火轮YY3568开发板技术参数详解
stm32单片机可以做什么简单的小作品呢?
苹果为何坚持禁用AppStore GetJar
高品质音乐芯片,支持U盘升级音频的MP3芯片,WT2003H4-16S
只需要一只铅笔,教你在家做电焊
大华股份步态识别技术再次取得新突破