C/C++ 内存管理(malloc/calloc/realloc、free 和 new 、 delete区别;内存泄漏)

2023-11-14

C/C++内存分布

int globalVar = 1;
static int staticGlobalVar = 1;
//globalVar和staticGlobalVar是在main函数之前初始化,在哪都能用,作用域是全局的
/*区别:它俩的链接属性不一样,globalVar是所有文件可见,staticGlobalVar只在当前文件可见*/
void Test()
{
 static int staticVar = 1; //运行到这里才初始化,它的作用域在Test函数中,只能在Test函数中使用
 int localVar = 1;
 
 int num1[10] = {1, 2, 3, 4};
 char char2[] = "abcd";   //一个栈上的数组
 char* pChar3 = "abcd";
 int* ptr1 = (int*)malloc(sizeof (int)*4);
 int* ptr2 = (int*)calloc(4, sizeof(int));
 int* ptr3 = (int*)realloc(ptr2, sizeof(int)*4);
 free (ptr1);
 free (ptr3);
}

globalVar在哪里?数据段
staticGlobalVar在哪里?数据段
staticVar在哪里?数据段
localVar在哪里?
num1 在哪里?__

char2在哪里?
*char2在哪里?_
pChar3在哪里?__
*pChar3在哪里?代码段
ptr1在哪里? *ptr1在哪里?_ 堆__

sizeof(num1) = 40;
sizeof(char2) = 5;
strlen(char2) = __4;
sizeof(pChar3) = 4/8;
strlen(pChar3) = 4;
sizeof(ptr1) = 4/8;
在这里插入图片描述

  • 栈(堆栈):非静态局部变量 / 函数参数 / 返回值等等,栈是向下增长的。
  • 内存映射段:是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口创建共享共
    享内存,做进程间通信。
  • 堆:用于程序运行时动态内存分配,堆是可以上增长的。
  • 数据段:存储全局数据和静态数据。
  • 代码段:可执行的代码 / 只读常量。

C语言中动态内存管理方式

malloc / calloc / realloc 和 free
malloc:申请空间;
calloc:申请空间并初始化为0;
realloc:对原来已经有的空间进行扩容。

C++内存管理方式

C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力而且使用起来比较麻烦,因此C++又提出
了自己的内存管理方式:通过new和delete操作符进行动态内存管理。

new / delete操作内置类型

申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用new[]和delete[]

void Test()
{
 // 动态申请一个int类型的空间
 int* ptr4 = new int;
 
 // 动态申请一个int类型的空间并初始化为3
 int* ptr5 = new int(3);
 
 // 动态申请3个int类型的空间
 int* ptr6 = new int[3];
 
 delete ptr4;
 delete ptr5;
 delete[] ptr6; }

在这里插入图片描述

new和delete操作自定义类型

在申请自定义类型的空间时,new 会调用构造函数,delete会调用析构函数,而malloc 和 free不会。

class Test
{
public:
 Test()
 : _data(0)
 {
 cout<<"Test():"<<this<<endl;
 }
 ~Test()
 {
 cout<<"~Test():"<<this<<endl;
 }
 
private:
 int _data;
};
void Test2()
{
 // 申请单个Test类型的空间
 Test* p1 = (Test*)malloc(sizeof(Test));
 free(p1);
 
 // 申请10个Test类型的空间
 Test* p2 = (Test*)malloc(sizoef(Test) * 10);
 free(p2);
}

void Test2()
{
 // 申请单个Test类型的对象
 Test* p1 = new Test;
 delete p1;
 
 // 申请10个Test类型的对象
 Test* p2 = new Test[10];
 delete[] p2; 
 }

malloc / free 和 new / delete 的区别

malloc/free和new/delete的共同点是:都是从堆上申请空间,并且需要用户手动释放。不同的地方是:

  1. malloc和free是函数,new和delete是操作符;
  2. malloc申请的空间不会初始化,new可以初始化;
  3. malloc申请空间时,需要手动计算空间大小并传递,new只需在其后跟上空间的类型即可;
  4. malloc的返回值为void*, 在使用时必须强转,new不需要,因为new后跟的是空间的类型;
  5. malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是new需要捕获异常;
  6. 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理。

malloc、operator new 和 new 的区别
malloc
operator new --> malloc+失败抛异常实现
new - - > operator new + 构造函数
new 比起malloc不一样的地方:1、调用构造函数初始化 2、失败了抛异常
delete 比如free不一样的地方:1、调用析构函数清理
operator free 和 free没区别,因为释放空间失败直接终止进程。 是因为要跟operator new成对出现才产生。

new和delete的实现原理

如果申请的是内置类型的空间,new和malloc,delete和free基本类似,不同的地方是:new/delete申请和
释放的是单个元素的空间,new[]和delete[]申请的是连续空间,而且new在申请空间失败时会抛异常,
malloc会返回NULL。

自定义类型

new的原理

  1. 调用operator new函数申请空间;
  2. 在申请的空间上执行构造函数,完成对象的构造;

delete的原理

  1. 在空间上执行析构函数,完成对象中资源的清理工作
  2. 调用operator delete函数释放对象的空间

new T[N]的原理

  1. 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请;
  2. 在申请的空间上执行N次构造函数;

delete[]的原理

  1. 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理
  2. 调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释放空间

内存泄露

内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而造成了内存的浪费。

内存泄露的危害:长期运行的程序出现内存泄漏,影响很大,如操作系统、后台服务等等,出现内存泄漏会导致响应越来越慢,最终卡死。

void MemoryLeaks()
 {
 // 1.内存申请了忘记释放
 int* p1 = (int*)malloc(sizeof(int));
 int* p2 = new int;
 
 // 2.异常安全问题
 int* p3 = new int[10];
 
 Func(); // 这里Func函数抛异常导致 delete[] p3未执行,p3没被释放.
 
 delete[] p3;
 }

内存泄露的分类

  • 堆内存泄露:程序执行中依据须要分配通过malloc / calloc / realloc / new等从堆中分配的一块内存,
    用完后必须通过调用相应的 free或者delete 删掉。假设程序的设计错误导致这部分内存没有被释放,那
    么以后这部分空间将无法再被使用,就会产生内存泄露。
  • 系统资源泄露:程序使用系统分配的资源,比方套接字、文件描述符、管道等没有使用对应的函数释放掉,导致系统资源的浪费,严重可导致系统效能减少,系统执行不稳定。

operator new 与 operator delete函数

new和delete是用户进行动态内存申请和释放的操作符,operator new 和operator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间。

#include <iostream>
using namespace std;

class A
{
public:
	A(int a = 0)
		:_a(a)
	{
		cout << "A()" << endl;
	}

	~A()
	{
		cout << "~A()" << endl;
	}
private:
	int _a;
};

int main()
{
	A* p1 = (A*)malloc(sizeof(A));
	A* p3 = (A*)operator new(sizeof(A));

	// operator new和malloc的区别是什么?
	// 结论:使用方式都一样,处理错误的方式不一样
	size_t size = 2;
	void* p4 = malloc(size*1024*1024*1024);
	cout << p4 << endl; // 失败返回0
	//free(p4);

	try
	{
		void* p5 = operator new(size * 1024 * 1024 * 1024);
		cout << p5 << endl; // 失败抛异常  (面向对象处理错的方式)
		//operator delete(p5);
	}
	catch (exception& e)
	{
		cout << e.what() << endl;
	}

	return 0;
}
struct ListNode
{
	ListNode* _next;
	ListNode* _prev;
	int _data;

	void* operator new(size_t n)
	{
		void* p = nullptr;
		p = allocator<ListNode>().allocate(1); // 内存池
		cout << "memory pool allocate" << endl;

		return p;
	}

	void operator delete(void* p)
	{
		allocator<ListNode>().deallocate((ListNode*)p, 1);
		cout << "memory pool deallocate" << endl;
	}
};

class List
{
public:
	List()
	{
		_head = new ListNode; // 全局operator new + 构造函数
		_head->_next = _head;
		_head->_prev = _head;
	}

	// void PushBack(int val);

	~List()
	{
		ListNode* cur = _head->_next;
		while (cur != _head)
		{
			ListNode* next = cur->_next;
			delete cur;
			cur = next;
		}

		delete _head;
		_head = nullptr;
	}

private:
	ListNode* _head;
};

int main()
{
	List l;

	return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C/C++ 内存管理(malloc/calloc/realloc、free 和 new 、 delete区别;内存泄漏) 的相关文章

  • 将复选框添加到 UniformGrid

    我正在尝试将复选框动态添加到 wpf 中的统一网格中 但看起来网格没有为它们分配足够的空间 所以它们都有点互相重叠 这就是我将它们添加到后面的代码中的方法 foreach string folder in subfolders PathCh
  • 如何检查图像对象与资源中的图像对象是否相同?

    所以我试图创建一个简单的程序 只需在单击图片框中更改图片即可 我目前只使用两张图片 所以我的图片框单击事件函数的代码 看起来像这样 private void pictureBox1 Click object sender EventArgs
  • 如何使 Windows 窗体的关闭按钮不关闭窗体但使其不可见?

    该表单有一个 NotifyIcon 对象 当用户单击 关闭 按钮时 我希望表单不关闭而是变得不可见 然后 如果用户想再次查看该表单 可以双击系统托盘中的图标 如果用户想关闭表单 可以右键单击该图标并选择 关闭 有人可以告诉我如何使关闭按钮不
  • 将数组向左或向右旋转一定数量的位置,复杂度为 o(n)

    我想编写一个程序 根据用户的输入 正 gt 负 include
  • pthread_cond_timedwait() 和 pthread_cond_broadcast() 解释

    因此 我在堆栈溢出和其他资源上进行了大量搜索 但我无法理解有关上述函数的一些内容 具体来说 1 当pthread cond timedwait 因为定时器值用完而返回时 它如何自动重新获取互斥锁 互斥锁可能被锁定在其他地方 例如 在生产者
  • 未解决的包含:“cocos2d.h” - Cocos2dx

    当我在 Eclipse 中导入 cocos2dx android 项目时 我的头文件上收到此警告 Unresolved inclusion cocos2d h 为什么是这样 它实际上困扰着我 该项目可以正确编译并运行 但我希望这种情况消失
  • WPF 中的调度程序和异步等待

    我正在尝试学习 WPF C 中的异步编程 但我陷入了异步编程和使用调度程序的困境 它们是不同的还是在相同的场景中使用 我愿意简短地回答这个问题 以免含糊不清 因为我知道我混淆了 WPF 中的概念和函数 但还不足以在功能上正确使用它 我在这里
  • 在 Visual Studio 2008 上设置预调试事件

    我想在 Visual Studio 中开始调试程序之前运行一个任务 我每次调试程序时都需要运行此任务 因此构建后事件还不够好 我查看了设置的 调试 选项卡 但没有这样的选项 有什么办法可以做到这一点吗 你唯一可以尝试的 IMO 就是尝试Co
  • Web API - 访问 DbContext 类中的 HttpContext

    在我的 C Web API 应用程序中 我添加了CreatedDate and CreatedBy所有表中的列 现在 每当在任何表中添加新记录时 我想填充这些列 为此目的我已经覆盖SaveChanges and SaveChangesAsy
  • 使用 System.Text.Json 即时格式化 JSON 流

    我有一个未缩进的 Json 字符串 例如 hash 123 id 456 我想缩进字符串并将其序列化为 JSON 文件 天真地 我可以使用缩进字符串Newtonsoft如下 using Newtonsoft Json Linq JToken
  • 如何将图像路径保存到Live Tile的WP8本地文件夹

    我正在更新我的 Windows Phone 应用程序以使用新的 WP8 文件存储 API 本地文件夹 而不是 WP7 API 隔离存储文件 旧的工作方法 这是我如何成功地将图像保存到 共享 ShellContent文件夹使用隔离存储文件方法
  • 从路径中获取文件夹名称

    我有一些路c server folderName1 another name something another folder 我如何从那里提取最后一个文件夹名称 我尝试了几件事 但没有成功 我只是不想寻找最后的 然后就去休息了 Thank
  • Github Action 在运行可执行文件时卡住

    我正在尝试设置运行google tests on a C repository using Github Actions正在运行的Windows Latest 构建过程完成 但是当运行测试时 它被卡住并且不执行从生成的可执行文件Visual
  • 将 unsigned char * (uint8_t *) 转换为 const char *

    我有一个带有 uint8 t 参数的函数 uint8 t ihex decode uint8 t in size t len uint8 t out uint8 t i hn ln for i 0 i lt len i 2 hn in i
  • 实体框架 4 DB 优先依赖注入?

    我更喜欢创建自己的数据库 设置索引 唯一约束等 使用 edmx 实体框架设计器 从数据库生成域模型是轻而易举的事 现在我有兴趣使用依赖注入来设置一些存储库 我查看了 StackOverflow 上的一些文章和帖子 似乎重点关注代码优先方法
  • 将 xml 反序列化为类,list<> 出现问题

    我有以下 XML
  • 插入记录后如何从SQL Server获取Identity值

    我在数据库中添加一条记录identity价值 我想在插入后获取身份值 我不想通过存储过程来做到这一点 这是我的代码 SQLString INSERT INTO myTable SQLString Cal1 Cal2 Cal3 Cal4 SQ
  • 控制到达非 void 函数末尾 -wreturn-type

    这是查找四个数字中的最大值的代码 include
  • 如何让Gtk+窗口背景透明?

    我想让 Gtk 窗口的背景透明 以便只有窗口中的小部件可见 我找到了一些教程 http mikehearn wordpress com 2006 03 26 gtk windows with alpha channels https web
  • C - 直接从键盘缓冲区读取

    这是C语言中的一个问题 如何直接读取键盘缓冲区中的数据 我想直接访问数据并将其存储在变量中 变量应该是什么数据类型 我需要它用于我们研究所目前正在开发的操作系统 它被称为 ICS OS 我不太清楚具体细节 它在 x86 32 位机器上运行

随机推荐

  • CentOS 8 通过二进制安装 MySQL

    需求 CentOS8下采用二进制安装包的形式安装MySQL 并且指定数据库文件存放的路径地址 步骤如下 在 MySQL下载地址 中下载 MySQL 二进制安装包 注意 在版本选择的时候 版本号在8 0 11及以下包后缀都是 tar gz 但
  • Python中from from __future__ import *的用法

    from future import 参考 https blog csdn net zzc15806 article details 81133045 我们在读代码的时候 总是会看到代码开头会加上from future import 这样的
  • NoClassDefFoundError/ClassNotFoundException 到底从哪引用到了这个类?排查思路

    1 背景 公司内网登录改造升级 使用方需要配合升级 jar 包 本以为很简单的事情 升级版本上线就 OK 了 没想到升级头一个服务 部署到测试环境就有问题 2 表象 访问所有页面报 404 3 排查思路 3 1 排除法 确定是不是升级 ja
  • cmd简单游戏代码_制作一个猜数字的游戏

    十一节假日 我在敲代码 外甥女突然问我 舅舅 你能不能给我编个游戏啊 看着外甥女期盼的眼神 我当然不好拒绝啊 而且如果写一点代码 能让小朋友对编程有个简单的了解 甚至激发她对编程学习的兴趣 那也是极好的啊 话不多说 我立马敲一个猜数字的文字
  • api-ms-win-core-path-l1-1-0.dll丢失怎么解决?

    api ms win core path l1 1 0 dll文件可以帮助用户快速的启动一些相关的应用程序 让应用程序可以正常的使用 但是近期有用户在电脑的使用中 遇到了系统提示提示 api ms win core path l1 1 0
  • Mysql的分布式(XA)真面目

    Mysql XA 一 XA是什么 二 MySQL中XA实现 1 内部XA事务 两阶段提交PC 2 外部XA事务 总结 一 XA是什么 XA 协议本就是为一个分布式事务协议 它规定了 XA PREPARE XA COMMIT XA ROLLB
  • [React] markdown以及markdown-navbar实现方案

    React markdown以及markdown navbar实现方案 1 前言 心血来潮 想在自己的项目中实现 Markdown 文件的渲染 以下是我当前的实现方式以及遇到的一些问题的记录 本人水平很拉 有更好的方法欢迎在下面讨论 2 m
  • C++ Primer阅读笔记--万能引用和引用折叠

    目录 1 万能引用 1 1 万能引用的实现 1 2 万能引用与右值引用的区别 2 引用折叠 1 万能引用 1 1 万能引用的实现 万能引用可以向其传递任何类型的参数 其会自动进行参数类型的推断 万能引用的两种实现如下 基于模板实现 temp
  • 【Ribbon路由规则器】服务筛选,过滤服务基础组件AbstractServerPredicate

    前言 Ribbon在进行Server过滤的时候 用到了一个重要的基础组件 AbstractServerPredicate 它的作用就是在众多Server的列表中通过一定的过滤策略踢除不合格的Server 留下来合格的Server列表 负载均
  • Matlab中值滤波

    medfilt2 是 MATLAB 中的一个函数 用于对二维图像进行中值滤波 中值滤波是一种非线性滤波方法 它将每个像素的值替换为该像素周围邻域内像素的中值 该函数语法如下 B medfilt2 A m n padopt 其中 A 是需要进
  • 三菱指令大全

    一 顺控指令 1 触点指令 00 LD 逻辑操作开始 01 LDI 逻辑非操作开始 02 AND 逻辑乘 03 ANI 逻辑乘非 04 OR 逻辑加 05 ORI 逻辑加非 2 连接指令 06 ANB AND逻辑块与 07 ORB OR逻辑
  • 嵌入式数据库Sqlite3.3.6移植教程

    本文介绍的内容都是基于Fedora10平台的 一 PC机编译安装 请阅读在安装包里的 INSTALL 文件 或者使用PEAR installer with pear install sqlite SQLite已经内置了 你不需要安装任何附加
  • 字符串数组中,strlen与sizeof的比较

    char str1 15 hello 用 赋值系统会在字符串结尾自动添 0 printf strlen str1 ld n strlen str1 printf sizeof str1 ld n sizeof str1 gt gt gt s
  • Ubuntu下,dpkg安装出错的修复

    参考 http www khattam info 2009 08 04 solved subprocess pre removal script returned error exit status 2 error 我在ubuntu上安装l
  • 【数学建模集训系列】公交查询系统的matlab实现-公交站点和线路对应矩阵

    功能 求站点S和路线L矩阵 表示通过S的所有线路 日期 8 9 2011 clear clc fid fopen Bus txt r 打开数据 if fid gt 0 disp 数据文件打开成功 else disp 打开失败 return
  • 【目标检测】yolov5模型详解

    文章目录 一 Yolov5网络结构 1 1 Input 1 2 Backbone 1 2 1 Conv模块 1 2 2 C3模块 1 2 3 SPPF模块 1 3 Neck 1 4 Head 1 4 1 head 1 4 2 目标框回归 1
  • react函数组件

    react 创建组件有三种方式 函数式定义的无状态组件 es5原生方式React createClass定义的组件 es6形式的extends React Component定义的组件 这篇我们主要讲函数组件的使用 在函数组件里面是没有生命
  • python selenium爬虫自动登录实例

    一 概述 我们要先安装selenium这个库 使用pip install selenium 命令安装 selenium这个库相当于机器模仿人的行为去点击浏览器上的元素 这时我们要用到一个浏览器的驱动 这里我用的是谷歌浏览器 二 安装驱动 确
  • Golang RabbitMQ实现的延时队列

    文章目录 前言 一 延时队列与应用场景 二 RabbitMQ如何实现延时队列 实现延时队列的基本要素 整体的实现原理如下 三 Go语言实战 生产者 消费者 前言 之前做秒杀商城项目的时候使用到了延时队列来解决订单超时问题 本博客就总结一下G
  • C/C++ 内存管理(malloc/calloc/realloc、free 和 new 、 delete区别;内存泄漏)

    C C 内存分布 int globalVar 1 static int staticGlobalVar 1 globalVar和staticGlobalVar是在main函数之前初始化 在哪都能用 作用域是全局的 区别 它俩的链接属性不一样