C和指针(八)动态内存分配

内存分配
1,数组元素存储在内存中连续位置上,数组声明时,所需要的内存在编绎时分配。
2,动态内存分配在运行时分配内存。
3,数组声明必须指定数组长度,但数组需要的长度在运行时才知道,通常做法是声明一个较大的数组,足以容纳最多元素,如果实际需要的元素数量较少时,造成内存浪费。

malloc和free
1,C函数库提供两个函数malloc和free,分别用于执行动态内存分配和释放。
2,malloc从内存池中获取一块合适的内存,并返回指向该内存的指针,需要手动对内存初始化。
3,当内存不再使用时free将内存归还内存池。

4,malloc在头文件stdlib.h中声明,参数是需要分配的内存字节数,分配的是一整块无类型的内存。
1)如果内存池中可用内存满足需求,返回指向分配内存块的起始位置指针,分配的是一块连续内存,实际内存可能比请求的多一点,由编绎器决定。
2)如果内存池无法满足内存分配请求,则向操作系统请求得到更多内存,并在新内存上执行分配任务,如果操作系统无法向malloc提供更多的内存,则malloc返回NULL指针。
3)需要对malloc返回的指针作非NULL判断。
4)malloc返回一个void*型指针,需要转换为其他类型。
5)要求边界对齐的机器,返回的内存起始位置满足边界对齐要求。
6)使用sizeof(类型)*长度分配指定长度指定类型的内存,程序可移植。
7)分配后的内存可使用间接访问以及下标访问数组的不同整数位置。

5,free的参数是先前从malloc、calloc、realloc返回的值,或NULL。

calloc和realloc
1,calloc分配内存后将内存初始化为0,参数为需要元素的个数和每个元素的字节数,根据这些值计算出总共需要分配的内存。

2,realloc用于修改一个原先已经分配内存块的大小,可扩大或缩小。
1)如果扩大一个内存块,内存块原先的内容保留,新增加的内存添加到原先内存块的后面,新内存不进行初始化。
2)如果无法在内存块尾部分配内存,重新分配一块内存将原先内容复制到新内存上,此时不能再使用指向旧内存的指针,使用返回的新指针。
3)如果缩小一个内存块,内存块尾部部分释放,其他部分原先内容保留。
4)如果第一个参数是NULL,与malloc功能一致。

注意
1,使用动态内存分配中,出现的问题包括:
1)对NULL指针进行解引用操作。
2)对分配的内存越界操作。
3)释放非动态分配的内存。
4)部分释放动态分配的内存。
5)动态内存释放后继续使用等。

2,使用sizeof计算元素类型长度与元素数目相乘得到需要的内存字节数。

3,malloc动态分配内存后,须确保返回的指针不是NULL,可#define malloc,防止其他代码块调用malloc,编绎器直接报错。

#include <stdlib.h>
#define malloc;
#define MALLOC(num, type)  (type*)alloc((num)*sizeof(type));
extern void* alloc(size_t size);

在自定义内存分配函数alloc中加入#undef指令,调用malloc获得动态内存,并确保返回的指针不是NULL。MALLOC宏接受元素的数目及元素的类型,计算总共需要的内存字节数。

#include <stdio.h>
#undef malloc

void* alloc(size_t size) {
    
    
	void *new_mem;
	new_mem = malloc(size);
	if (new_mem == NULL) {
    
    
		printf(" Out of memory!\n" );
		exit(1);
	}
	return new_mem;
}

4,内存越界,访问的内存可能保存了其他变量的值,如果进行修改将破坏原变量的值。
5,内存池以链表的形式维护可用内存池,访问分配内存之外的区域可能破坏链表。
6,free释放非动态分配的内存可能导致程序终止,部分释放动态分配的内存也可能导致程序终止。
7,realloc可以缩小一块动态分配的内存,有效地释放尾部的内存。
8,当动态分配内存的指针存在多份拷贝,无法保证在使用其中一个指针时内存是否被其他指针释放,必须确保内存释放后程序停止使用这块内存。
9,内存使用完后不进行释放则会造成内存泄露,程序可能耗尽可用内存,如果操作系统所有程序共享一个通用内存池,内存泄漏可能榨干所有可用内存,只能重启系统。

扫描二维码关注公众号,回复: 15492088 查看本文章

总结
1,声明数组时,必须在编绎时知道长度,动态内存分配可为运行时知道长度的数组分配内存。

2,malloc和calloc都用于动态分配一块内存,并返回指向该内存块的指针。
1)malloc的参数是需要分配的内存字节数。
2)calloc参数是需要分配的元素个数和元素长度,并将内存初始化为0。

3,realloc改变一块已动态分配的内存大小,增加内存块大小可能采取将原来内存块上内容复制到新的内存上。
4,当动态分配内存不再使用时,调用free释放内存,内存释放后不可再访问。
5,如果请求内存分配失败,返回NULL指针,内存越界访问还可能破坏可用内存池。

猜你喜欢

转载自blog.csdn.net/mei_true/article/details/131382499