系统学习之C复习(11)动态内存管理

c语言中,我们关注内存中存在的:  (除此以外还有其他区) 
栈区    
        局部变量
        函数的形式参数(形参)
堆区
        malloc/free
        calloc
        realloc
        动态内存分配
静态区 
        全局变量
        静态变量(const)

动态内存管理主要的四个函数

#include <stdlib.h>    //动态内存头文件

mallco和free 

void* malloc(size_t size);
这个函数向内存申请一块连续可用的空间,并返回指向这块空间的指针。
void free (void* ptr);
如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的。
如果参数 ptr 是NULL指针,则函数什么事都不做。

int main()
{
	int* ptr = (int*)malloc(40);	//malloc向堆区申请了40个字节,返回void*类型。我们强制转换为int*类型
	int* p = ptr;	//确保申请的空间的起始地址不丢失
	if (p == NULL)
	{
		perror("malloc"); //如果开辟失败,则用perror返回错误原因
		return 1;
	}
	//memset(p, 0, 40);		//初始化p地址开始的40个字节的空间
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		*p = i;
		p++;
	}//此处为申请的40字节的空间初始化
	//用完该空间后不需要,则释放空间 free
	free(ptr);	//从申请的空间的起始地址 开始释放,所以需要ptr
	ptr = NULL; //释放后,ptr成为了野指针,置为 NULL 空指针

	return 0;
}

calloc

void* calloc(size_t num, size_t size);
用于申请内存并初始化为0

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


realloc

void* realloc (void* ptr, size_t size);
调整申请的内存空间的大小

int main()
{
	int* p = (int*)malloc(40);	
	if (p == NULL)
	{
		perror("malloc");
		return 1;
	}
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		*(p+i) = i;
	}
	//当空间不够,希望可以放20个元素,需要realloc扩容
	int* ptr = (int*)realloc(p, 80);//整体变成80字节。不是追加80个字节	
	//此处两种情况
	if (ptr != NULL)
	{
		p = ptr;
	}
	//扩容成功,开始使用。
	
	//不再使用
	free(p);
	p = NULL;

	return 0;
}

上述的两种情况:

1.如果后续的空间足够扩容,那么就延续p的地址后面的空间进行扩容
        p[][][][][][][](后面扩容)[][][][][][][]
2.如果后续的空间不足够扩容,那么它会在内存的其他地方寻找一个足够的空间,并将p的内容转移到新空间后继续扩容,同时将会free释放掉p原本的空间 所以为了防止扩容失败(找不到足够的空间)且释放了原本了空间,进行int* ptr = realloc(p,80);  确保成功后再将ptr赋值给p 

常见内存的错误 

1.对空指针的解引用
    解决办法:对malloc函数返回值进行空指针判定
    if (p == NULL)
    {
        perror("malloc"); //如果开辟失败,则用perror返回错误原因
        return 1;
    }
2.对动态内存开辟空间的越界访问
3.对非动态开辟内存使用free释放
4.使用free释放一块动态开辟内存的一部分
5.对同一块动态内存多次释放
    void test()
    {
        int *p = (int *)malloc(100);
        free(p);
        free(p);//重复释放
    }
6.动态开辟内存忘记释放(内存泄漏)

经典面试题

void GetMemory(char* p)
{
	p = (char*)malloc(100);
}
void main(void)
{
	char* str = NULL;
	GetMemory(str);
	if (str == NULL)
	{
		perror("malloc");
	}
	strcpy(str, "hello world");
	printf(str);
}
运行报错,p是形参。结束后 str依旧是空指针。
错误类型:对空指针的解引用,程序崩溃
修改为正确:
void GetMemory(char** p)
{
	*p = (char*)malloc(100);
}
void main(void)
{
	char* str = NULL;
	GetMemory(&str);
	if (str == NULL)
	{
		perror("malloc");
	}
	strcpy(str, "hello world");
	printf(str);
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值