C++ 内存管理 常考面试题总结

1. 什么是内存泄漏,如何避免?

  • 定义:堆内存分配后,指针丢失或未释放,导致内存无法回收,长期占用系统资源。
  • 避免方法:优先使用智能指针(unique_ptr/shared_ptr),自动管理内存;遵循RAII原则,资源获取即初始化;避免裸指针,使用容器管理动态对象;工具检测:Valgrind、AddressSanitizer等。

2. std::unique_ptr和std::shared_ptr的区别是什么?

3. 如何调试和解决内存泄漏问题?

  • 工具检测:Valgrind:valgrind --leak-check=full ./程序,定位泄漏位置;AddressSanitizer:编译时加-fsanitize=address,运行时实时检测;内置工具:VS的内存诊断、GDB的内存追踪。
  • 代码层面:检查new/delete配对,避免裸指针;用智能指针替代手动管理;排查异常导致的delete未执行场景。

4. C++的内存分配模型是什么?

  • 栈分配:函数调用时自动分配,函数返回自动释放,速度快、大小有限。
  • 堆分配:new/malloc手动分配,delete/free手动释放,灵活但易泄漏。
  • 静态存储:全局/静态变量,程序启动分配,结束释放。
  • 常量存储:字符串常量、const全局变量,只读。

5. 解释栈和堆内存,它们的区别?

6. 指针悬挂(Dangling Pointer)和野指针(Wild Pointer)的区别?

  • 指针悬挂:指向的内存已释放(如delete后未置空),指针非空,访问触发未定义行为。
  • 野指针:未初始化的指针,值为随机垃圾值,指向不可控内存,风险更高。
  • 规避:悬挂指针释放后置nullptr;野指针定义时立即初始化。

7. RAII如何协助资源管理与内存泄漏防止?

  • 核心定义:资源获取即初始化(Resource Acquisition Is Initialization),将资源生命周期与对象绑定。
  • 实现逻辑:构造函数获取资源(如内存、文件句柄);析构函数自动释放资源,无需手动管理;
  • 典型应用:智能指针、锁守卫、文件流,从根本上避免泄漏。

8. 简述堆和栈的区别

与第5题答案一致。

9. malloc和局部变量分配在堆还是栈?

  • malloc分配在堆,需手动释放;
  • 局部变量分配在栈,函数返回自动释放。

10. 程序有哪些section,分别的作用?程序启动的过程?怎么判断数据分配在栈上还是堆上?

程序section

  • 代码段(Text):可执行代码、只读常量,共享且只读;
  • 数据段(Data):已初始化的全局/静态变量;
  • BSS段:未初始化的全局/静态变量,程序启动时清零;
  • 栈段:局部变量、函数参数、返回地址;
  • 堆段:new/malloc分配的内存。

程序启动过程

  1. 加载可执行文件到内存;
  2. 初始化BSS段,清零未初始化全局变量;
  3. 执行_start函数,调用main函数;
  4. 执行main函数,程序运行。

判断分配位置

  • 栈:局部变量、函数参数,地址接近栈顶(高地址);
  • 堆:new/malloc分配,地址接近堆底(低地址);
  • 静态/全局:地址固定,位于数据段/BSS段。

11. 初始化为0的全局变量在bss还是data?

  • 初始化为0的全局变量存放在BSS段,程序启动时自动清零;
  • 非0初始化的全局变量存放在数据段。

12. 你知道C++内存分配可能会出现哪些问题?

  • 内存泄漏:堆内存未释放,长期占用;
  • 野指针/悬挂指针:访问无效内存;
  • 内存碎片:频繁分配释放导致小块内存无法利用;
  • 栈溢出:递归过深或局部变量过大;
  • 越界访问:数组越界,破坏内存布局。

13. 什么是内存碎片,怎么避免内存碎片?

  • 定义:堆中大量小空闲内存块,无法满足大内存分配,导致内存利用率低。
  • 避免方法:使用内存池,预分配大块内存,减少碎片;避免频繁分配释放小块内存;优先使用栈分配,减少堆使用。

14. 什么是野指针?如何预防呢?

  • 定义:未初始化的指针,值为随机垃圾值,指向不可控内存。
  • 预防:指针定义时立即初始化(如int* p = nullptr);释放内存后置空;避免使用未初始化的局部指针。

15. 内存对齐应用于哪几种数据类型及其

  • 所有内置类型(char、short、int、float、double等)和自定义结构体/类;
  • 对齐规则:成员起始地址为自身大小的整数倍,结构体总大小为最大成员大小的整数倍。

16. 内存池的作用及其实现方法

  • 作用:预分配大块内存,减少频繁分配释放的开销,避免内存碎片,提升性能。
  • 实现方法:固定大小内存块:预分配多个相同大小的块,按需分配释放;可变大小内存块:按需求分配不同大小的块,合并空闲块;典型应用:STL容器、网络库、游戏引擎。

17. new/delete 和 malloc/free 的区别?

  • 性质:new/delete 是 C++ 运算符,malloc/free 是 C 库函数。
  • 初始化:new 会调用构造函数初始化对象,malloc 仅分配内存不初始化。
  • 类型安全:new 返回指定类型指针,malloc 返回 void*,需强制转换。
  • 分配失败:new 抛出 bad_alloc 异常,malloc 返回 NULL。
  • 数组支持:new[] 分配数组并调用多次构造,delete[] 释放并调用多次析构;malloc 需手动计算数组大小。

18. 什么是内存映射文件(mmap)?有什

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

C++ 常考面试题总结 文章被收录于专栏

本专栏系统梳理C++方向, 大中厂高频高频面试考点 , 内容皆来自真实面试经历,从基础语法、内存管理、STL与设计模式,到操作系统与项目实战,结合真实面试题深度解析,帮助开发者高效查漏补缺,提升技术理解与面试通过率,打造扎实的C++工程能力.

全部评论
感谢分享
点赞 回复 分享
发布于 02-26 22:26 黑龙江
谢谢
点赞 回复 分享
发布于 02-26 22:19 湖北
不够吧
点赞 回复 分享
发布于 02-26 21:42 云南

相关推荐

02-25 11:00
点赞 评论 收藏
分享
评论
5
7
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务