(c语言进阶)动态内存管理

一.为什么要有动态内存管理

二.malloc和free

malloc函数———动态申请内存

基础概念 :头文件<stdlib.h>

应用方法  

#include <stdio.h>
#include<stdlib.h>
int main()
{
	//开辟40个字节的内存空间,将空间首地址指向p
	int* p = (int*)malloc(40);
	//判断申请内存空间是否成功
	if (p == NULL)
	{
		perror("malloc");
		return 1;
	}
	int i = 0;
	//给开辟的空间赋值
	for (i = 0; i < 10; i++)
	{
		*(p + i) = i;
	}
	//输出内容
	for (i = 0; i < 10; i++)
	{
		printf("%d ",*(p+i));
	}
	return 0;
}

#include <stdio.h>
#include<stdlib.h>
int main()
{
	int* p = (int*)malloc(4000000000000000);
	//判断申请内存空间是否成功
	if (p == NULL)
	{
		perror("malloc");
		return 1;
	}
	int i = 0;
	//给开辟的空间赋值
	for (i = 0; i < 10; i++)
	{
		*(p + i) = i;
	}
	//输出内容
	for (i = 0; i < 10; i++)
	{
		printf("%d ",*(p+i));
	}
	return 0;
}

free函数——接收内存首地址,释放动态申请的内存。

基础概念:头文件:<stdlib.h>

应用 

#include <stdio.h>
#include<stdlib.h>
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;
	}
	//输出内容
	for (i = 0; i < 10; i++)
	{
		printf("%d ",*(p+i));
	}
	//释放内存
	free(p);
	//为了避免p指向的空间无意义,成为野指针,将p赋值为空;
	p = NULL;
	return 0;
}

三.calloc和realloc

calloc函数=malloc+将申请的内存中每个字节初始化为0

基础概念

应用 

#include <stdio.h>
#include<stdlib.h>
int main()
{
	int* p = (int*)calloc(10,sizeof(int));
	//判断申请内存空间是否成功
	if (p == NULL)
	{
		perror("malloc");
		return 1;
	}
	int i = 0;
	//输出内容
	for (i = 0; i < 10; i++)
	{
		printf("%d ",*(p+i));
	}
	//释放内存
	free(p);
	//为了避免p指向的空间无意义,成为野指针,将p赋值为空;
	p = NULL;
	return 0;
}

realloc函数 ——动态调整动态内存大小

基础概念 

应用 

#include <stdio.h>
#include<stdlib.h>
int main()
{
	int* p = (int*)calloc(10,sizeof(int));
	//判断申请内存空间是否成功
	if (p == NULL)
	{
		perror("malloc");
		return 1;
	}
	int i = 0;
	//输出内容
	for (i = 0; i < 10; i++)
	{
		printf("%d ",*(p+i));
	}
	//内存不够,扩大到20个整形大小
	int* ptr=realloc(p, 20 * sizeof(int));
	//如果修改内存成功,则把新内存的首地址指向p
	if (ptr != NULL)
	{
		p = ptr;
	}
	//释放内存
	free(p);
	//为了避免p指向的空间无意义,成为野指针,将p赋值为空;
	p = NULL;
	return 0;
}

调整内存失败和成功后出现的结果 

 

 realloc也可以当做malloc来用

#include <stdio.h>
#include<stdlib.h>
int main()
{
	int* p = (int*)realloc(NULL,10*sizeof(int));
	//判断申请内存空间是否成功
	if (p == NULL)
	{
		perror("malloc");
		return 1;
	}
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		*(p + i) = i;
	}
	//输出内容
	for (i = 0; i < 10; i++)
	{
		printf("%d ",*(p+i));
	}
	//释放内存
	free(p);
	//为了避免p指向的空间无意义,成为野指针,将p赋值为空;
	p = NULL;
	return 0;
}

四.常见的动态内存的错误

1.对NULL指针的解引用操作

#include <stdio.h>
#include<stdlib.h>
int main()
{
	int* p = (int*)malloc(40);
	//如果内存申请失败,则p有可能是空指针,空指针不可解引用
	*p = 20;
	free(p);
	return 0;
}

2.对动态开辟空间的越界访问

#include <stdio.h>
#include<stdlib.h>
int main()
{
	int* p = (int*)malloc(40);
	if (p == NULL)
	{
		perror("malloc");
		return 1;
	}
	int i;
	for (i = 0; i <= 10; i++)//开辟了十个整形的大小,访问到第十一个时越界
	{
		*(p + i) = i;
	}
	free(p);
	p = NULL;
	return 0;
}

3.对非动态开辟内存使用free释放

#include <stdio.h>
#include<stdlib.h>
int main()
{
	int a = 10;
	int* p = (int*)malloc(40);
	if (p == NULL)
	{
		perror("malloc");
		return 1;
	}
	p = &a;
	//此时p指向的不再是动态申请的内存
	free(p);
	//无法释放非动态申请的内存
	p = NULL;
	return 0;
}

4.使用free释放一块动态开辟内存的一部分

#include <stdio.h>
#include<stdlib.h>
int main()
{
	int* p = (int*)malloc(40);
	if (p == NULL)
	{
		perror("malloc");
		return 1;
	}
	p++;
	//此时p指向的已经不是内存的首地址了,只能释放其中的一部分内存
	//报错
	free(p);
	p = NULL;
	return 0;
}

5.对同一块动态内存多次释放

#include <stdio.h>
#include<stdlib.h>
int main()
{
	int* p = (int*)malloc(40);
	if (p == NULL)
	{
		perror("malloc");
		return 1;
	}
	free(p);
	//对同一块内存重复释放,对不存在的内存进行释放,报错
	free(p);
	p = NULL;
	return 0;
}

6.动态开辟内存忘记释放(内存泄露)

#include <stdio.h>
#include<stdlib.h>
int main()
{
	int* p = (int*)malloc(40);
	if (p == NULL)
	{
		perror("malloc");
		return 1;
	}
	//申请的内存由于死循环永远无法释放,导致内存泄露
	while (1);
	free(p);
	p = NULL;
	return 0;
}

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-01-21 20:46:01       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-01-21 20:46:01       100 阅读
  3. 在Django里面运行非项目文件

    2024-01-21 20:46:01       82 阅读
  4. Python语言-面向对象

    2024-01-21 20:46:01       91 阅读

热门阅读

  1. C++学习笔记(四十三):c++ optional

    2024-01-21 20:46:01       48 阅读
  2. react和vue的区别

    2024-01-21 20:46:01       52 阅读
  3. 【Delphi 基础知识 22】TStringList 的详细用法

    2024-01-21 20:46:01       49 阅读
  4. CSS Day10

    CSS Day10

    2024-01-21 20:46:01      46 阅读
  5. Linux设置nginx开机自启动

    2024-01-21 20:46:01       52 阅读
  6. C# 字符串(String)

    2024-01-21 20:46:01       55 阅读
  7. datasets的一些使用技巧

    2024-01-21 20:46:01       51 阅读
  8. 【智驾未来】低代码开发:加速创新交融的利器

    2024-01-21 20:46:01       54 阅读
  9. C# 程序结构

    2024-01-21 20:46:01       47 阅读