[C语言]动态内存管理

1. 内存的四区模型

在这里插入图片描述

2. 动态内存管理

  由上图可知,属于程序员管理的内存空间只有堆区,所以动态内存管理都是在堆区进行的。

1). 动态内存管理的意义

  通过局部变量去申请内存空间,大小固定,不利于后期扩展。所以产生了动态内存管理的这个概念。

2). 动态内存函数malloc() free()

1>. malloc()函数介绍
函数原型:

void* malloc(size_t size);

函数作用:
  向内存申请一块连续可用的空间,并返回这块空间的首地址。申请失败则返回NULL。
说明:
  这块空间是由程序员进行分配管理,所以在程序没有结束运行,系统都不会自动释放这块空间,所以就要额外注意这块空间的释放。

2>. free()函数介绍
函数原型:

void free(void* ptr);

函数作用:
  用来释放动态开辟的内存。
说明:
  free之后 虽然空间被释放了,但是指针依旧指向原来的内存空间,如果对指针做操作,仍然可以操作该空间,可能会导致程序崩溃。 一般在free内存空间后,要对 指针赋值为NULL,防止误操作。

3). 通过动态内存函数创建数组及二维数组示例

// 创建一维数组
int* ptr = (int*)malloc(num * sizeof(int));
// 判断申请内存空间是否成功
if(NULL == ptr)
{
	exit(0);
}
// 初始化内存空间
for(int i = 0; i < num; i++)
{
	ptr[i] = 0;
}
// 释放内存空间
free(ptr);
// 释放完后,赋值为NULL 防止误操作
ptr = NULL;

创建二维数组

// 创建一个字符串数组
// 动态分配一个数组,数组中的每个元素都是char*
// 相当于创建二维数组的 str[][] 第一个方括号
char** str = (char**)malloc(n * sizeof(char*));
// 判断是否申请成功
if(str == NULL)
{
	exit(0);
}
// 对数组中元素再次进行内存空间的申请
// 相当于创建二维数组 str[][] 第二个括号
for(int i = 0; i < n; i++)
{
	str[i] = (char*)malloc(len * sizeof(char));
}
// 初始化与二维数组操作相同
// 释放空间 需要分两次释放
// 1.先释放二维数组中每个元素的空间
for(int i = 0; i < n; i++)
{
	free(str[i]);
	str[i] = NULL;
}
// 2. 释放n个长度的str
if(str != NULL)
{
	free(str);
	str = NULL:
}

2. realloc()函数

函数原型:

void* realloc(void* ptr, size_t size);

函数作用:
  可以调整已经申请的内存空间大小,并且会将原空间的数据移动到新空间。
参数列表:
*ptr: 要调整的内存地址
size: 调整之后的新大小
返回值:调整内存空间之后的空间起始地址。

realloc()函数的模拟实现:

void* my_realloc(void* memblock, size_t size)
{
	// 1.申请新的内存空间
	void* new_base = malloc(size);
	if(new_base != NULL)
	{
		return -1;
	}
	// 2.拷贝数据
	memcpy(new_base, memblock, size);
	// 3.释放原来的内存空间
	free(memblock);
	// 4.返回新空间首地址
	return new_base;
}

3. 常见的动态内存错误

  1. 对NULL指针的接引用操作
  2. 对动态开辟空间的越界访问
  3. 对非动态开辟内存使用free释放
  4. 使用free释放一块动态开辟内存的一部分
int *p = (int*)malloc(10);
p++;	// p的起始位置发生了改变
free(p); // err
  1. 对同一块内存释放了多次
  2. 动态开辟内存忘记释放

4. 柔性数组

1). 定义

结构体中最后一个元素是未知大小的数组。

struct Test
{
	int i;
	int a[0]; // 柔性数组
};

2). 特点

  1. 结构体中的柔性数组成员前面必须只有有一个其他类型成员。
  2. sizeof计算结构体大小,不包含柔性数组
  3. 包含柔性数组成员的结构用malloc()函数进行内存动态分配,并且分配的内存大小应该大于结构体的大小,以适应柔性数组的预期大小。

3).使用

int i  = 0;
Test *p = (Test*)malloc(sizeof(Test) + 100*sizeof(int));
p->i = 100;
// 柔性数组a获得了100个整形连续空间
for(int i = 0 ; i < 100; i++)
{
   p->a[i] = i;
}

// 释放空间
free(p);

如果不采用柔性数组实现相同功能,释放内存空间需要释放先释放结构体内部申请的一维数组空间,在释放整个结构体空间。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值