C++重点知识(动态内存管理)

发布于:2025-06-25 ⋅ 阅读:(16) ⋅ 点赞:(0)

C/C++程序将内存分为那些区?为什么进行分区?

  • 分区
    • 栈区:由编译器自动分配和释放,用于存放函数的参数值、局部变量等
    • 堆区:由程序员手动分配和释放,用于动态内存分配
    • 全局区:用于存放全局变量和静态变量。程序开始运行时分配内存,结束时释放
    • 常量区:存放常量数据,如字符串常量,const修饰的变量等
    • 代码区:存放函数体的二进制代码。是只读的
  • 分区原因
    • 管理方便
    • 数据保护
    • 支持动态分配
    • 提高程序运行效率

malloc实现原理

  • malloc的实现依赖操作系统提供的底层内存分配接口
    • brk/sbrk:通过移动进程的堆顶指针来扩展或收缩堆空间
      • 适合分配小块内存,但频繁调用会出现内存碎片
    • mmap:通过映射文件或匿名区域到进程地址空间,分配较大内存
      • 分配的内存独立于堆,释放时直接归还操作系统,减少碎片

new和delete的实现原理

  • new(opeartor new + 构造函数

    • 调用void* operator new(size_t size)申请空间
      • 循环调用malloc申请空间
      • 如果malloc申请空间成功则返回,失败先检测用户是否设置空间不足应对措施,如果提供调用malloc申请,如果没有提供,抛出bad_alloc异常
    • 对申请好的空间调用构造函数进行初始化
  • delete(析构函数 + operator delete

    • 调用对应类型的析构函数,完成对象中资源的清理工作
    • 调用void operator delete(void* p)函数完成空间的释放工作,而函数中真正的释放是使用free进行的
  • new T[N]

    • 调用void* operator new[](size_t size)函数来申请空间
      • 该函数中实际调用void* operator new来完成申请的
    • 调用N次构造函数,对N个对象的空间从前往后进行初始化
  • tedele[] p

    • 调用N次析构,完成空间中N个对象中的资源清理工作
    • 调用void operator delete[](void* p)
      • 实际是调用void operator delete(void* p)完成工作

new/delete和malloc/free的区别

  • 相同点
    • 都是用来动态申请内存空间
    • 申请的空间在用完后都必须手动释放
  • 不同点
    • malloc和free是函数,new和delete是操作符
    • malloc申请不会初始化,new可以初始化
    • malloc申请空间时,需要手动计算空间大小并传递,new只需在其后跟上空间的类型即可
    • malloc的返回值为void*,在使用时必须强转,new不需要
    • malloc申请失败时,返回值是NULL,因此使用时需要判空,new不需要,但时new要捕获异常
    • 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造和析构

什么是内存泄漏?内存泄漏的危害?

  • 定义:内存泄漏是程序在运行过程中,动态分配了内存空间,但使用完毕后,没有及时将这些内存释放回系统,导致这部分内存无法再次利用,随着程序的运行,泄漏的内存不断积累
  • 内存泄漏的危害
    • 系统资源耗尽
    • 性能下降
    • 程序异常
    • 影响系统稳定

如何避免内存泄漏

  • 仔细检查动态内存分配和释放
  • 使用智能指针


网站公告

今日签到

点亮在社区的每一天
去签到