IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【C语言】-动态内存管理 -> 正文阅读

[C++知识库]【C语言】-动态内存管理


前言

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

我们学习过变量,学习过数组。
但是我们知道,我们声明变量时,例如int型变量,它其实是在栈上开辟了4个字节的空间,当我们声明长度为10,类型为int型的数组时,它其实是在栈上开辟了40个字节的空间,一旦我们实现开辟好,那么就面临一个问题,这个空间多了还是少了?用不用的完?用不完会造成空间浪费,而少了会导致内存溢出。
这时候,动态内存分配就起到了作用。


1、动态内存管理函数的介绍

1.1、malloc和free

C语言给我们提供了动态开辟内存的函数:malloc

malloc函数的基本形式:

void* malloc(size_t size);

malloc函数的作用:

向内存申请一块size个字节大小的空间。

函数的返回值:

  • 如果开辟成功,则返回开辟好的空间的地址。
  • 如果开辟失败,则返回空指针NULL,这也就是为什么malloc空间之后一定要做指针是否为NULL的判断的原因。

malloc函数使用时需要注意的事项:

  • malloc函数返回的是void*型的指针,所以需要我们在使用时,自己将指针转换为我们需要的指针类型。
  • size的大小为0时,malloc的行为是未定义的,具体取决于编译器。这个行为一般没有什么意义。
  • 返回的指针用p接收了之后,就不要随意改动p的位置,因为当我们改动了p的位置之后,我们就找不到那片空间的起始位置了,而当我们free的时候又是以p为起始位置开始释放那片空间。最好的解决办法就是先将p赋给p1,让p1去变动。
  • 把p指针free之后,要记得把p指针置为NULL,因为此时p指向的那片空间已经还给操作系统了,此时p指针属于野指针。

C语言给我们提供了用来释放动态开辟的内存的工具:free
free函数使用的注意事项:

  • 如果参数指针指向的空间不是动态开辟的,那么free函数的行为是未定义的。
  • 如果参数指针是NULL指针,则函数就什么都不做。

ps:malloc和free都声明在stdlib.h头文件中
使用案例:

#include <stdio.h>
int main()
{
 //代码1
 int num = 0;
 scanf("%d", &num);
 int arr[num] = {0};
 //代码2
 int* ptr = NULL;
 ptr = (int*)malloc(num*sizeof(int));
 if(NULL != ptr)//判断ptr指针是否为空
 {
 int i = 0;
 for(i=0; i<num; i++)
 {
 *(ptr+i) = 0}
 }
 free(ptr);//释放ptr所指向的动态内存
 ptr = NULL;//是否有必要?
 return 0;
}

1.2、calloc

C语言提供了一个函数叫calloc,calloc也可以用来动态内存分配。
calloc基本样式如下:

void* calloc(size_t num,size_t size);

calloc的基本功能:

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

ps:calloc和malloc的区别只在于calloc会在返回地址之前把申请的内存空间每个字节全都初始化为0。

1.3、realloc

同样的,realloc也是C语言给我们提供的函数
realloc函数的基本形式:

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

realloc函数的功能:

调整申请的空间的大小。ptr是要调整的内存地址,size是调整之后的大小。返回调整之后的内存的起始地址。

realloc函数的注意事项:

涉及到调整大小,那么就会出现一个问题:如果我要在原有空间的基础上调大空间,但是后面没有足够大的空间了怎么办?

![在这里插入图片描述](https://img-blog.csdnimg.cn/c758d49e30854635a768c86601e3f903.png
在这里插入图片描述

2、常见动态内存的错误

2.1、对NULL指针的解引用

void test()
{
 int *p = (int *)malloc(INT_MAX/4);
 *p = 20;//如果p的值是NULL,就会有问题
 free(p);
}

这就犯了我们前面提到的错误,malloc之后要判断返回的指针是否为NULL指针

2.2、对动态开辟空间的越界访问

void test()
{
 int i = 0;
 int *p = (int *)malloc(10*sizeof(int));
 if(NULL == p)
 {
 exit(EXIT_FAILURE);
 }
 for(i=0; i<=10; i++)
 {
 *(p+i) = i;//当i是10的时候越界访问
 }
 free(p);
}

当我们用指针接收了开辟的内存的地址后,我们对这个开辟的内存地址外的地址进行访问。 因为外面那片空间不属于我们,导致了对开辟空间的越界访问。

2.3、对非动态开辟的内存空间使用了free释放

void test()
{
 int a = 10;
 int *p = &a;
 free(p);//ok?
}

我们前面提到,free只能对动态开辟的内存空间使用。这里对非动态开辟的内存进行了释放是错误的。

2.4、使用free释放了一块动态开辟的内存的一部分

void test()
{
 int *p = (int *)malloc(100);
 p++;
 free(p);//p不再指向动态内存的起始位置
}

我们前面提到,我们尽量不要对p指针进行修改,修改后p指针就没有指向那块空间的起始地址了,这时候free(p)的话就只释放掉了动态开辟的内存的后面那部分。我们在使用那块空间时,应该声明一个变量p1,把p指向的地址赋给p1。

3.5、对同一块动态内存的多次释放

void test()
{
 int *p = (int *)malloc(100);
 free(p);
 free(p);//重复释放
}

3.6、动态开辟的内存未释放(内存泄漏)

void test()
{
 int *p = (int *)malloc(100);
 if(NULL != p)
 {
 *p = 20;
 }
}
int main()
{
 test();
 while(1);
}

忘记释放会导致,每次调用这个函数都会在内存开辟一块空间,这样空间越来越少,最终导致死机,关机重启之后程序又能继续运行。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-11-05 00:06:35  更:2022-11-05 00:07:38 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 15:29:41-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码