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分配的内存。
程序启动过程
- 加载可执行文件到内存;
- 初始化BSS段,清零未初始化全局变量;
- 执行_start函数,调用main函数;
- 执行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++工程能力.
