当前位置: 首页 > article >正文

C/C++——内存管理

1. 内存管理的定义

内存管理是指操作系统或应用程序对计算机资源的分配、使用和释放的管理过程

2. 内存管理的作用

优化内存的利用率,确保程序能够正常运行,并提高系统的性能和稳定性

3. 内存的分配和释放

3.1 静态内存分配

静态内存分配是指在程序编译时就确定了内存的分配和释放。在静态内存分配中,内存的大小和生命周期是固定的,无法动态改变。

常见的静态内存分配方式:

全局变量:全局变量在程序运行期间始终存在,其内存分配在程序启动时就完成了,知道程序结束时才会结束。

静态局部变量:静态局部变量和普通变量的区别在于静态局部变量的生命周期不随函数的调用而结束。

静态数组:静态数组的大小在编译时就完成了,并且在程序运行期间始终存在,程序结束时才会被释放。

#include<iostream>
using namespace std;
//全局变量
int num1 = 10;
//静态局部变量
void foo()
{
	static int num2 = 20;
	cout << "静态局部变量num2:" << num2 << endl;
	num2++;
}
int main()
{
	//静态数组
	int StaticArray[5] = { 1,2,3,4,5 };
	//输出全局变量
	cout << "全局变量num1:" << num1<<endl;
	//调用函数多次输出静态局部变量
	for (int i = 0; i < 3; i++)
	{
		foo();
	}
	//输出静态数组
	cout << "静态数组StaticArray:";
	for (int i = 0; i < 5; i++)
	{
		cout << StaticArray[i] <<" ";
	}
	cout << endl;
	return 0;
}
//全局变量num1:10
//静态局部变量num2:20
//静态局部变量num2:21
//静态局部变量num2:22
//静态数组StaticArray:1 2 3 4 5

3.2 动态内存分配

动态内存分配是指在程序运行时根据需要动态地申请和释放空间。动态内存的好处是可以根据实际需要动态地调整内存空间的大小,从而提高内存的利用率。但是在使用完以后一定要记得释放,以免造成内存泄露。

int size = 5;  // 数组大小
int* arr = new int[size];  // 动态分配内存

// 初始化数组
for (int i = 0; i < size; i++) {
    arr[i] = i + 1;
}

// 打印数组元素
for (int i = 0; i < size; i++) {
    cout << arr[i] << " ";
}

delete[] arr;  // 释放内存

3.3 内存释放

内存释放的实现方法:

**手动释放:**C语言使用free()函数,C++中使用delete操作符

**自动释放:**通过垃圾回收机制自动释放不再使用的内存。

**智能指针:**智能指针是一种特殊的指针对象,它能够自动管理内存的释放。智能指针可以有效地避免内存泄露多次释放同一块内存的问题。

内存释放的注意事项

**释放内存的顺序:**如果存在多个指针指向同一块内存空间,需要按照分配的顺序进去释放,以免多次释放同一块空间的问题。

**释放后的指针置空:**在释放内存后,最好将指针置空,以避免野指针的出现。

**避免重复释放:**同一块内存空间只需要释放一次,重复释放会导致程序奔溃或其他错误。

4. C语言和C++动态内存管理的区别

4.1 不同点:

  1. C语言使用malloc()free(),C++使用newdelete
  2. malloc()free()函数是C标准库函数,需要包含头文件才可以使用;而newdelete操作符是C++的关键字,可以直接使用
  3. 在C语言中,malloc()函数需要手动释放,而new操作符分配的内存通过delete操作符自动释放
  4. 在C中,malloc()函数返回的内存块的大小是以字节为单位的,而在C++中,new操作数返回的内存块的大小是以对象为单位指定的
  5. 在C++中,new操作数可以自动调用类的构造函数初始化,而malloc()函数只会简单的分配内存,不会自动初始化
  6. 在C++中,delete操作符可以自动调用类的析构函数,而free()函数只是简单的释放动态分配的内存

4.2 共同点:

都是从堆上申请空间,并且需要用户手动释放

5. 内存泄漏

内存泄漏是指程序在运行过程中,由于错误的使用或者逻辑错误,导致申请的内存空间无法被正常释放,从而造成内存的浪费。内存泄漏会导致系统内存资源逐渐耗尽,进而影响系统的正常运行。

5.1 造成内存泄漏的原因

未释放动态分配的内存:在使用动态内存分配函数(如malloc、new等)申请内存后,如果没有使用对应的释放函数(如free、delete等)进行释放,就会导致内存泄漏。

int* ptr = new int;
// 没有使用delete释放内存

循环引用:循环引用指的是两个或多个对象之间相互引用,导致它们的引用计数无法归零,从而导致内存泄漏。

class A:
    def __init__(self):
        self.b = None

class B:
    def __init__(self):
        self.a = None

a = A()
b = B()
a.b = b
b.a = a

未关闭资源:在程序中使用了一些需要手动关闭的资源,如文件、数据库连接等,如果没有正确关闭这些资源,就会导致内存泄漏。

FileInputStream fis = null;
try {
    fis = new FileInputStream("file.txt");
    // 使用文件资源
} catch (IOException e) {
    e.printStackTrace();
} finally {
    // 没有关闭文件资源
}

缓存未清理:在程序中使用了缓存,但是没有及时清理缓存中的过期数据,就会导致内存泄漏。

cache = {}
def get_data(key):
    if key not in cache:
        # 从数据库中获取数据
        cache[key] = data
    return cache[key]

5.2 如何避免内存泄漏

  1. 及时释放内存资源
  2. 避免循环引用
  3. 使用内存管理工具
  4. 优化代码和数据结构

http://www.kler.cn/news/163222.html

相关文章:

  • 微软NativeApi-NtQuerySystemInformation
  • 【WPF.NET开发】WPF中的对话框
  • 拆分降采样与归一化(LN和BN)
  • websocket vue操作
  • 快速学会绘制Pyqt5中的所有图(下)
  • Kafka安全性探究:构建可信赖的分布式消息系统
  • 二叉树的非递归遍历(详解)
  • 一款可无限扩展的软件定时器开源框架项目代码
  • 三星AI笔电:年底大战一触即发,行业变革在即
  • 【数据结构和算法】种花问题
  • 快速搭建MyBatis源码调试环境
  • 麒麟V10服务器安装Apache+PHP
  • 基于OpenCV的人脸识别系统案例
  • 交换排序(冒泡排序)(快速排序(1))
  • ElasticSearch之Task management API
  • SQLite基本使用
  • mybatis和mybatisplus中对 同namespace 中id重复处理逻辑源码解析
  • 关于前端原生技术-Jsonp的理解与简述
  • 如何快速构建知识服务平台,打造个人或企业私域流量
  • 二维码智慧门牌管理系统:升级解决方案实现多领域数据综合应用
  • WPF实现文字纵向排布的TabItem
  • 使用 HTML 地标角色提高可访问性
  • printf二进制输出
  • 线程安全与并发区别
  • java中synchronized关键字的用法
  • 带你真正理解web地图切片规则
  • 智能优化算法应用:基于指数分布算法无线传感器网络(WSN)覆盖优化 - 附代码
  • 初识 pytest 及断言使用
  • 风控反欺诈安全学习路标
  • JumpServer初探