首页 > 系统相关 >C++ 内存管理

C++ 内存管理

时间:2024-07-07 20:26:05浏览次数:17  
标签:Node malloc 管理 C++ 内存 operator new delete

内存管理

C/C++ 内存分布

  1. 静态区(数据段)
    • 全局变量:在整个程序运行期间都存在的变量,包括没有显式声明为static的全局变量。
    • 静态局部变量:在函数内部声明为static的变量。它们在函数首次调用时初始化,并在程序整个运行期间保持其值。
    • 静态全局变量:在文件作用域中声明为static的变量。它们只在声明它的文件中可见,并在整个程序运行期间存在。
  2. 常亮区(代码段)
    • 字符串字面量:如"Hello"这样的字符串字面量存储在常量区,不可修改。
    • 常量数据:使用const关键字声明且初始化的常量数据也通常存放在常量区。
    • 局部自动变量:在函数内部声明的非静态局部变量,随函数调用入栈和出栈。
    • 函数调用的参数:传递给函数的参数通常存储在栈中。
    • 局部数组和结构体:在函数内部声明的数组和结构体也会存储在栈中。
    • 动态分配的内存:通过malloc()calloc()realloc()等函数申请的内存存储在堆中。这些内存需要通过free()释放以避免内存泄漏。

【说明】

  • 生命周期:数据的生命周期是关键因素。全局的静态数据具有较长的生命周期,存储在静态区;局部自动变量和函数参数生命周期较短,存储在栈中。
  • 可变性:常量数据存储常量区,因为它们不可更改。
  • 动态需求:堆用于满足运行时动态大小的需求,如动态数组或链表节点。

image-20240704110919552

image-20240704111000518

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

malloc:申请一块指定大小的连续内存区域,返回指向这块内存的指针。

calloc:同malloc并将内容初始化为0.

realloc:对已分配内存块改变大小,如果原内存块无法调整大小,realloc尝试分配一块新内存,并复制原有内容。

free:释放malloccallocrealloc申请的内存,防止内存泄漏。

图片

new/delete操作内置类型

image-20240704133638511

**注意:**申请和释放单个元素的空间,使用newdelete操作符,申请和释放连续的空间,使用new[]delete[],匹配使用。

image-20240704134122978

既然已经有了mallocfreenewdelete的意义何在?

  1. 对于上面内置类型,他们效果是一样的。
  2. 对于自定义类型,效果就不一样。malloc只申请空间。new申请空间+构造函数初始化

**注意:**在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而mallocfree不会。

new和delete操作自定义类型

  • 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来释放空间。
typedef struct LinstNode_C {
	int _val;
	struct ListNode* _next;
	struct ListNode* _prve;
}Node;
Node* Init(int x) {
	Node* node = (Node*)malloc(sizeof(Node) * x);
	node->_val = x;
	node->_prve = NULL;
	node->_next = NULL;
	return node;
}
void Destory(Node* node){
	// ……
}

typedef struct ListNode_CPP {
	int _val;
	struct ListNode_CPP* _next;		// C++兼容c的用法
	ListNode_CPP* _prve;			// 升级版struct 更方便

	ListNode_CPP(int x = 0)
		:_val(x)
		,_prve(nullptr)
		,_next(nullptr)
	{ 
		cout << "Init()" << endl;
	}
	~ListNode_CPP() {
		cout << "~delete()" << _val << endl;
	}
}Node_cpp;
Node* d1 = (Node*)malloc(sizeof(Node));

Node_cpp* d2 = new Node_cpp(5);
Node_cpp* d3 = new Node_cpp[5];
delete d2;
delete[] d3;		// 调用相应空间个数的析构函数

new/delete操作内置类型

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

size_t size = 2;
void* p4 = malloc(size * 1024 * 1024 * 1024 * 1024);
cout << p4 << endl;		// 溢出返回0
// free(p4);
try {
	void* p5 = operator new(size * 1024 * 1024 * 1024 * 1024);
	cout << p5 << endl;		// 溢出报错
	//operator delete(p5);
}
catch(exception& e){
	cout << e.what() << endl;
}
  • operator newmalloc的区别是什么?结论:使用方式都一样,处理错误的方式不一样

总结:mallocfree、和newdelete的区别
malloc/freenew/delete的共同点是:都是从堆上申请空间,并且需要用户手动释放。不同的地方是:

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

内存泄漏

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

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

标签:Node,malloc,管理,C++,内存,operator,new,delete
From: https://blog.csdn.net/Long_kin/article/details/140249854

相关文章

  • 学生管理系统(通过顺序表,获取连续堆区空间实现)
    将学生的信息,以顺序表的方式存储(堆区),并且实现封装函数:1】顺序表的创建,2】判满、3】判空、4】往顺序表里增加学生信息、5】遍历学生信息6】任意位置插入学生信息7】任意位置删除学生信息8】修改学生信息9】查找(按学生的学号查找)、10】删除重复学生信息11】销毁顺序......
  • Java计算机毕业设计美容机构管理系统(开题+源码+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着人们生活水平的提高和美容意识的增强,美容行业迎来了前所未有的发展机遇。然而,传统的美容机构管理模式往往存在效率低下、信息孤岛、顾客体验不佳......
  • Java计算机毕业设计酒店管理网站(开题+源码+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着旅游业的蓬勃发展,酒店行业作为旅游产业链中的关键环节,面临着日益激烈的市场竞争和多元化的客户需求。传统的酒店管理模式已难以满足现代顾客对于......
  • 【Spring Boot】基于 JPA 开发的文章管理系统(CRUD)
    《JPA从入门到精通》系列包含以下文章:Java持久层API:JPA认识JPA的接口JPA的查询方式基于JPA开发的文章管理系统(CRUD)关系映射开发(一):一对一映射关系映射开发(二):一对多映射关系映射开发(三):多对多映射基于JPA开发的文章管理系统(CRUD)1.实现文章实体2.实现......
  • RedHat7.4—配置与管理iptables防火墙
    假如某公司需要Internet接入.采用iptables作为NAT服务器接入网络,为确保安全需要配置防火墙功能,要求内部仅能够访问Web、DNS及Mail三台服务器;1、内网通过防火墙访问外网1.1、配置主机网络内部Web服务器通过端口映象方式对外提供服务。内网服务器地址网卡1IP设为192.168.100.1......
  • 配置与管理squid代理服务器
    应用背景如下图所示,公司用squid作代理服务器,代理服务器内网IP地址为192.168.200.1,外网IP为192.168.200.3公司内网所用IP地址段为192.168.200.0/24,并且想用8080作为代理端口。1:配置非透明代理1.1、配置主机网络准备三台Linux主机,第一台为外网主机名为www,网卡(Vmnet1)IP为218.2......
  • RedHat7.4—配置远程管理Linux服务器
    公司的Linux服务器需24小时不间断工作,维护工程师希望通过设置能远程管理和维护服务器。要求通过SSH及VNC远程管理,实现如下配置需求:可以通过SSH服务访问远程主机,可以使用证书登录远程主机,不需要输入远程主机的用户名和密码可以使用VNC服务访问远程主机,使用图形界面访问,桌面端口......
  • 打印100以内所有能被3整除的数,每5个数打印一行(devC++)
     今天让我们来学习如何利用C语言,在运行框中打印100以内所有能被3整除的数,每五个数打印一行。 首先,我们需要定义两个变量,其中n表示1~100的数字,m表示3的倍数的个数。然后利用一个for循环,在循环中n自增,利用一个if判断语句判断是否为3的倍数,如果是,则输出在循环中再利用一个......
  • 【操作系统】进程管理——调度算法(个人笔记)
    学习日期:2024.7.4内容摘要:各种调度算法的思想、规则、优缺点介绍为什么要有调度算法?调度算法就好比一群人在银行办理业务,准备办理业务的人就是进程/作业,银行窗口的工作人员就是CPU,进程往往是比CPU数目多的。调度算法就是决定,哪些人可以先被服务,哪些人要排队等待。适用于批......
  • 基于 LSN 的 PostgreSQL 数据管理与恢复
    在数据管理和恢复中,LSN(LogSequenceNumber)起着至关重要的作用。本文将深入探讨LSN在PITR(时间点恢复)、流复制、日志记录以及数据一致性中的具体应用,并详细介绍如何基于LSN进行时间点恢复。1.基本概念1.1LSNLSN(LogSequenceNumber,日志序列号)是PostgreSQL中用于......