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++知识库]C/C++ 动态内存管理函数的学习记录

前言

本博客介绍4个动态内存管理相关函数malloc、calloc、realloc、free。这四个函数被包含在头文件<stdlib.h>或<malloc.h>中。

函数介绍

1. malloc

首先看c语言对malloc函数的定义:
在这里插入图片描述
malloc函数,功能为在堆区中申请一块单位为byte的内存空间,并返回指向此空间的void类型指针。
用例:

int* ptr = (int *)malloc(40);

此代码意为在堆区中申请一块大小为40byte的空间,并通过强制类型转换,返回类型为(int*)的指针ptr。由此我们就得到了堆区上一块能够存储10个int类型数据的内存空间。

如果开辟失败,则malloc会返回空指针NULL。我们可以添加一段判空代码来判断malloc的空间开辟是否成功。

int* ptr = (int *)malloc(40);
if (ptr == NULL)
{
	perror("malloc");
	return;
}

其中perror("malloc");可以帮助我们在程序运行后,如果出现开辟空间失败时,打印一段错误信息,让我们知道是在malloc这个环节出错了。

2. calloc

calloc函数与malloc函数的不同在于,其会将所申请内存的每一个字节初始化为0。
在这里插入图片描述

int* ptr = (int *)calloc(40);
if (ptr == NULL)
{
	perror("calloc");
	return;
}

同样在调用calloc后进行判空。

3.realloc

realloc函数的功能为:调整堆区上申请的空间大小。
如:

int* ptr = (int *)malloc(40);
if (ptr == NULL)
{
	perror("malloc");
	return;
}
int* tmp = realloc(ptr,80);
if(tmp!=NULL)
{
	ptr=tmp;
}

运行此代码段,在realloc增容成功的情况下,我们可以将ptr的大小由原来的40个字节调整为80个字节。
在增容成功后,realloc会返回其调整大小后内存空间的起始地址。
realloc和malloc、calloc一样,如果空间开辟失败,则会返回一个空指针NULL。
需要注意的是,在realloc失败的情况下,如果不进行判空就将realloc的返回值赋给ptr,会使ptr成为空指针,我们也就丢失了之前在ptr所指向空间的存储内容。
因此我们需要创建一个临时变量tmp,对tmp进行判空,如果tmp != NULL是成立的,说明realloc增容成功。此时令ptr = tmp是安全的。

realloc在调整内存空间的是存在两种情况:
情况1:原有空间之后有足够大的空间,此时调整好大小后直接返回原有空间的起始地址。当对原有空间进行缩容时,也属于这种情况。
情况2:原有空间之后没有足够大的空间,此时realloc函数会在堆区种重新寻找一块内存空间进行开辟,并将原ptr所指向空间中所存储的数据拷贝至新开辟的空间中。随后,realloc会将ptr所指向的空间free掉,并返回新开辟空间的起始地址。
如下图:
在这里插入图片描述

4. free

free函数的作用:释放堆区上所开辟的空间。
如果使用malloc、calloc在堆区上开辟了空间,却在使用完空间后没有释放,这会造成内存泄漏问题。

内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了内存的浪费。(摘自维基百科)

free的使用:

int* ptr = (int *)malloc(40);
if (ptr == NULL)
{
	perror("malloc");
	return;
}
int* tmp = realloc(ptr,80);
if(tmp!=NULL)
{
	ptr=tmp;
}
//使用目标空间
……
//使用完成后进行释放
free(ptr);
ptr=NULL;

free(ptr)后记得要对ptr进行置空,否则会使ptr成为野指针。因为free只是释放了ptr所指向的内存空间,并没有改变ptr的指向。

动态内存管理中的常见错误

1. 对NULL指针的解引用操作(不进行开辟空间后的判空)

malloc可能存在开辟空间失败的情况。如不对malloc进行判空就解引用,就会出错。

int* ptr = (int*)malloc(INT_MAX);//这个数非常大,malloc无法开辟如此大的内存空间
*ptr = 1;//因为malloc开辟失败会返回空指针,此时*ptr是有问题的。

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

int* ptr = (int*)malloc(40);
if (ptr == NULL)
{
	perror("malloc");
	return;
}
for(int i = 0;i <= 10;i++)
{
	*(ptr + i) = i;//ptr所指向的空间只有40,但当i=10时,会越界访问4个字节。
	//为保证程序正常运行,一是需要不越界访问,二可以添加一个增容函数,当存储空间满时,进行增容。
}

包含增容功能的代码如下:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>

int* expand(int** ptr,int* vol)
{
	return (int*)realloc(*ptr, sizeof(int) * (*vol + 2));
}
int main()
{
	int* ptr = (int*)malloc(40);
	int sz = 0;
	int vol = 10;
	
	if (ptr == NULL)
	{
		perror("malloc");
		return 1;
	}
	
	for (int i = 0; i <= 10; i++)
	{
		if (sz == vol) 
		{
			int* tmp=expand(&ptr, &vol);
			if (tmp != NULL)
			{
				ptr = tmp;
			}
		}
		
		*(ptr + i) = i;
		sz++;
	}
	return 0;
}

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

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

4. 部分释放动态开辟的内存空间

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

运行后结果如下:
在这里插入图片描述
因此,要注意在编写动态开辟内存空间的代码时,最好不要更改起始地址的指向。可以写成*(ptr + i)的形式。

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

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

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-08-19 18:45:50  更:2022-08-19 18:47:11 
 
开发: 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年5日历 -2024/5/10 7:35:55-

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