0
点赞
收藏
分享

微信扫一扫

动态内存管理详解

心存浪漫 2022-04-03 阅读 91

目录

为什么存在动态内存分配?

动态内存函数

1.malloc

            如果参数 size 为0,malloc的行为是标准是未定义的,取决于编译器。2.free

3.calloc

常见的动态内存错误:

面试题:


为什么存在动态内存分配?

int main()
{
	int ret = 0;//在栈区开辟四个字节
	char arr[10] = { 0 };//在栈区开辟10个字节的连续空间

	return 0;
}

特点:

  • 空间大小是确定的(固定的);
  • 数组在声明的时候,指定多少个字节,则内存就分配多少空间。

对于空间需求我们不仅仅局限于固定值,某些情况我们不能确定所需空间大小。这时我们就需要动态内存开辟

补充:动态内存都是在堆区开辟,由程序员主动或程序结束自动释放。

动态内存函数

1.malloc

意义:向内存申请一块连续内存空间,返回指向这块内存的指针。

 注意:返回值的类型是void*  需要程序员自己确定(强转)。

            如果参数 size 为0,malloc的行为是标准是未定义的,取决于编译器。
2.free

意义:释放动态开辟的内存 

 注意:如果参数不是指向动态开辟的,则free函数的行为是未定义的。

如果参数是NULL指针,则函数什么也不做。

代码:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
int main()
{
	//int ret = 0;//在栈区开辟四个字节
	//char arr[10] = { 0 };//在栈区开辟10个字节的连续空间
	int* ptr = 0;
	ptr = (int *)malloc(sizeof(int) * 10);//开辟10个4个字节的数据
	if (ptr == NULL)//判断是否开辟成功
	{
		perror("malloc");
	}
	for (int i = 0; i < 10; i++)
	{
		*(ptr + i) = i;//赋值
	}
	for (int j = 0; j < 10; j++)
	{
		printf("%d ", *(ptr + j));
	}
	free(ptr);
	ptr = NULL;

	return 0;
}

3.calloc

意义:为 num 个大小为 size 的元素开辟一块空间,并且把空间的每个字节初始化为0。

和malloc相似,区别:元素会被初始化(每个字节初始化为0)

 

 代码:

int main()
{
	int* ptr = 0;
	ptr =(int*) calloc(10, sizeof(int));
	if (ptr == NULL)
	{
		perror("calloc");
	}
	for (int i = 0; i < 10; i++)//
	{
		printf("%d ", *(ptr + i));
	}
	printf("\n");
    free(ptr);
	ptr = NULL;
	return 0;
}

 4.realloc

 让动态开辟更加灵活,某些情况开辟的太大或太小,所以为了更灵活,realloc可以对动态开辟进行调整。

 

 两种特殊情况:

1.原有空间之后有足够的空间。

2.没有足够的空间。

 代码:

int main()
{
	int* ptr = 0;
	ptr = (int*)malloc(sizeof(int)*10);//申请10个4个字节数据
	if (ptr == NULL)
	{
		perror("malloc");
	}
	for (int i = 0; i < 10; i++)
	{
		*(ptr + i) = i;
	}
	int* p = (int*)realloc(ptr,sizeof(int) * 20);//追加10个4字节的空间
	if (p == NULL)
	{
		perror("realloc");
	}
	ptr = p;
	for (int j = 10; j < 20; j++)
	{
		*(ptr + j) = j;
	}
	for (int m = 0; m < 20; m++)
	{

		printf("%d ", *(ptr + m));
	}
	free(ptr);
	ptr = NULL;
		return 0;
}

常见的动态内存错误:

     //对NULL指针解引用
    //对动态开辟内存越界访问   
    //对非动态内存开辟进行free   
    //使用free释放动态开辟的一部分    
    //对一块动态内存连续释放    
    //动态开辟忘记释放.....会造成内存泄露;

void test1()
{
	//对NULL指针解引用
	int* p = (int*)malloc(sizeof(int));
	*p = 20;//没有进行判断若p为NULL,是有问题的。
	free(p);
	p = NULL;

}
void test2()
{
	int* p = (int*)malloc(sizeof(int) * 10);
	if (p == NULL)
	{
		perror("malloc");
	}
	for (int i = 0; i < 20; i++)
	{
		*(p + i) = i;
	}
	free(p);
	p = NULL;
}
void test3()
{
	int a = 10;
	int* p = &a;
	free(p);
	p = NULL;

}
void test4()
{
	int* p = (int*)malloc(sizeof(int) * 10);
	if (p == NULL)
	{
		perror("malloc");
	}
	for (int i = 0; i < 5; i++)
	{
		*(p++) = i;
	}
	free(p);//这是的p不指向动态开辟的起始地址。
}
void test5()
{
	int* p = (int*)malloc(sizeof(int) * 10);
	free(p);
	free(p);


}
void test6()
{
	while (1)
	{
		int* p = (int*)malloc(sizeof(int));
		if (p == NULL)
		{
			perror("malloc");
		}
		*p = 20;
	}
}
int main()
{
	//对NULL指针解引用
	//test1();
	//对动态开辟内存越界访问
	//test2();
	//对非动态内存开辟进行free
	//test3();
	//使用free释放动态开辟的一部分
	//test4();
	//对一块动态内存连续释放
	//test5();
	//动态开辟忘记释放.....会造成内存泄露;
	test6();

	return 0;
}

面试题:

1.

#include<string.h>
void GetMemory(char* p)
{
	p= (char*)malloc(100);
}
void Test(void)
{
	char* str = NULL;
	GetMemory(str);//这里是传值,所以不会改变实参,无意义
	strcpy(str, "hello world");
	printf(str);//程序崩溃,啥都没有。
}

int main()
{
	Test();
	return 0;
}

2.

char* GetMemory(void)
{
	char p[] = "hello world";
	return p;//返回p的内容会被销毁,
}
void Test(void)
{
	char* str = NULL;
	str = GetMemory();//所以str野指针
	printf(str);//打印随机
}

int main()
{
	Test();
	return 0;
}
举报

相关推荐

0 条评论