c_动态内存管理

动态内存管理

        需要的空间大小在程序运行时才能知道,为了满足这种需求,需要动态分配空间。

一、动态内存函数

1、malloc函数

原型:void *malloc(size_t size);
申请一个连续可用的空间( 以字节为单位),并返回指向这块空间的指针(申请成功)或者返回一个NULL指针(申请失败);

2、free函数

原型:void free(void *ptr);
释放动态开辟的空间:仅仅是 去掉ptr指针和动态开辟的空间的关联

3、calloc函数

原型:void *calloc(size_t num, size_t size);
功能和malloc的唯一区别就是,为num个大小为size的元素开辟一块空间,并将每个空间都初始化为0。

4、realloc函数

原型:void *realloc(void *ptr,size_t size);
对申请的空间大小进行调整。
在扩大原空间时,有两种情况
    1、 原有空间之后有足够多的空间时,在原有内存之后直接追加空间;
    2、原有空间之后没有足够多的空间时,在堆空间上另找一个合适大小的连续空间来使用。
特注:用realloc函数申请时,考虑到申请失败
ptr = realloc(ptr, 1000);
当申请失败后原空间数据就会丢失,所以这种做法是错误的。
正确的做法:
p = realloc(ptr,1000);
if(p != NULL){
   ptr = p;
}
二、总:动态开辟空间的的四大步
    1、动态申请空间;//申请的空间必比期望申请的空间大,所以一般建议大块申请。
    2、判空(可能存在申请失败);
    3、释放空间free;//释放掉后,ptr为野指针(悬垂指针)。
    4、将ptr指向NULL。

三、关于动态内存的几点注意:
    1、动态申请完,必须要判空;
    2、释放内存free函数必须释放的是动态申请的空间(堆上开辟的空间);
    3、必须整体申请,整体释放;
四、几个练习
1、Test运行的结果,原因
解析:
正确执行:(改正)

方法1,传址操作:将变量str的地址作为函数参数
char * GetMemory(char **p)
{
	*p = (char *)malloc(100);
}
void Test(void)
{
	char *str = NULL;
	GetMemory(&str);
	if (str != NULL){
		strcpy(str, "hello");
		printf(str);
	}
	free(str);//str为空时,函数什么事都不做
	str = NULL;
}
运行成功,结果:hello

方法2:通过函数返回值动态开辟,不传参
char * GetMemory()
{
	char *p;
	p = (char *)malloc(100);
	if (p != NULL){
		return p;
	}
}
void Test(void)
{
	char *str = GetMemory();
	strcpy(str, "hello");
	printf(str);
	free(str);
	str = NULL;
}

运行成功,结果:hello
2、运行Test函数,结果,原因
char * GetMemory(void)
{
	char p[] = "hello";
	return p;
}
void Test(void)
{
	char *str = NULL;
	str = GetMemory(); 
	printf(str);
}

编译通过,但不会输出hello(已测试过)
原因:GetMemory函数的数组p是保存在此 函数的栈帧上,函数运行完,栈帧被释放掉,但是释放仅是失效,数组还是存在的,
但是!!!,调用完GetMemory函数,接下来调用的是printf函数,是函数调用就会形成栈帧,则就会覆盖GetMemory函数的栈帧(当前已无效),所以,不会输出“hello”。
五、柔性数组

定义: 结构体中的最后一个元素允许是未知大小的数组,该数组就是柔性数组。
特点:
    1、结构体中的柔性数组成员前面必须至少有一个其他成员;
    2、结构体的大小不包括柔性数组的内存;
    3、包含柔性数组成员的结构体用malloc函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。
优势:方便内存释放
使用:
typedef struct st_type{
	int i;
	int a[0];//柔性数组
}type_a;

int  main()
{
	int i = 0;
	type_a *p = (type_a *)malloc(sizeof(type_a) + 100 * sizeof(int));
	if (p != NULL){
		p->i = 100;
		for (i = 0; i < 100; i++){
			p->a[i] = i;
		}
	}
	free(p);
	p = NULL;

	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/tec_1535/article/details/80508424