【C++】内存管理常见面试题

简介: 【C++】内存管理常见面试题

Ⅰ.  内存管理常见面试题

0x00  malloc / free 和 new / delete 的区别

malloc / free 和 new / delete 共同点:都是从堆上申请空间,并且需要用户手动释放。

不同点如下:(围绕着用法上的区别底层的区别)

① malloc /  free 是函数,而 new / delete 是操作符。

② malloc 申请的空间不会初始化,new 可以初始化。

③ malloc 申请空间时,需要手动计算空间的大小并传递,new 只需在其后跟上空间的类型即可。

④ malloc 的返回值为 void* ,因此在使用时必须强制类型转换,而 new 不需要,因为 new 后面跟的是空间的类型。

⑤ malloc 申请空间失败时,返回的是 NULL,因此使用时出于安全角度需要对其进行判空处理。而 new 不需要,但是 new 需要捕获异常。

⑥ 申请自定义类型对象时,malloc / free 只会开空间和清理空间。而 new 申请空间后会调用构造函数完成对象的初始化,delete 在释放空间前会调用析构函数完成空间中资源的清理。

Ⅱ.  内存泄露

0x00 什么是内存泄露?内存泄露的危害?

什么是内存泄露 —— 动态申请的内存,不使用了,有没有主动释放,就存在内存泄露。
内存泄露的危害 ——
a. 出现内存泄露的进程正常结束,进程结束时这些内存会还给系统,不会有什么大的伤害。
b. 出现内存泄露的进程的非正常结束,比如僵尸进程。
c. 需要长期运行的程序,出现内存泄露。危害很大,系统会越来越慢,甚至卡死宕机。
    (服务器程序、后台程序)

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

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

void MemoryLeaks() {
  // 1.内存申请了忘记释放
  int* p1 = (int*)malloc(sizeof(int));
  int* p2 = new int;
  // 2.异常安全问题
  int* p3 = new int[10];
  Func(); // 这里Func函数抛异常导致 delete[] p3未执行,p3没被释放。
  delete[] p3;
}

0x01 内存泄露分类

C / C++ 程序中,我们一般关心两种方面的内存泄露:

堆内存泄露(Heap Leak)

堆内存指的是程序执行中语句须分配通过 malloc / calloc / realloc / new 等从堆中分配的一块内存,用完后必须通过调用相应的 free 或者 delete 删掉。假设程序的设计错误导致这部分内存没有释放,那么以后这部分空间将无法再被实用,就会产生 Heap Leak。

系统资源泄露

之程序使用系统分配资源,比如套接字(两个网络各自通信连接中的端点)、文件描述符、管道等没有使用对应的函数释放掉,导致系统资源的浪费,严重可导致系统效能减少,系统执行不稳定。

0x02 如何检测内存泄露

Linux 下内存泄露检测

在windows下使用第三方工具

其他工具

0x03 如何避免内存泄露

① 工程前期良好的设计规范,养成良好的编码规范,申请的内存空间记着匹配地去释放。(ps:这个是理想状态,但是如果碰上异常时,就算注意释放了,还是可能会出现问题,需要下一条智能指针来管理才有保证)。

② 采用 RAII 思想(资源获取即初始思想)或者智能指针来管理资源。

③ 有些公司内部规范使用内部实现的私有内存管理库。这套库自带内存泄漏检测的功能选项。

④ 出问题了使用内存泄露工具检测(ps:不过很多工具不够靠谱,或者收费昂贵)。

🔺 总结:内存泄露非常常见,解决方案分为两种:

① 提前预防型:如智能指针等。

② 事后查错型:如泄露检测工具。


 

 

 

相关文章
|
21天前
|
存储 编译器 C语言
内存管理【C++】
内存管理【C++】
35 1
|
1月前
|
存储 编译器 C语言
【C++】C\C++内存管理
【C++】C\C++内存管理
【C++】C\C++内存管理
|
1月前
|
存储 安全 Java
JVM常见面试题(二):JVM是什么、由哪些部分组成、运行流程,JDK、JRE、JVM关系;程序计数器,堆,虚拟机栈,堆栈的区别是什么,方法区,直接内存
JVM常见面试题(二):JVM是什么、由哪些部分组成、运行流程是什么,JDK、JRE、JVM的联系与区别;什么是程序计数器,堆,虚拟机栈,栈内存溢出,堆栈的区别是什么,方法区,直接内存
JVM常见面试题(二):JVM是什么、由哪些部分组成、运行流程,JDK、JRE、JVM关系;程序计数器,堆,虚拟机栈,堆栈的区别是什么,方法区,直接内存
|
1月前
|
编译器 C++
virtual类的使用方法问题之C++类中的非静态数据成员是进行内存对齐的如何解决
virtual类的使用方法问题之C++类中的非静态数据成员是进行内存对齐的如何解决
|
14天前
|
C语言 C++
C++(二)内存管理
本文档详细介绍了C++中的内存管理机制,特别是`new`和`delete`关键字的使用方法。首先通过示例代码展示了如何使用`new`和`delete`进行单个变量和数组的内存分配与释放。接着讨论了内存申请失败时的处理方式,包括直接抛出异常、使用`try/catch`捕获异常、设置`set_new_handler`函数以及不抛出异常的处理方式。通过这些方法,可以有效避免内存泄漏和多重释放的问题。
|
1月前
|
存储 Java C语言
【C++】C/C++内存管理
【C++】C/C++内存管理
|
1月前
|
存储 编译器 C语言
C++内存管理(区别C语言)深度对比
C++内存管理(区别C语言)深度对比
60 5
|
29天前
|
存储 程序员 编译器
c++学习笔记08 内存分区、new和delete的用法
C++内存管理的学习笔记08,介绍了内存分区的概念,包括代码区、全局区、堆区和栈区,以及如何在堆区使用`new`和`delete`进行内存分配和释放。
37 0
|
2月前
|
NoSQL Redis C++
c++开发redis module问题之在复杂的Redis模块中,特别是使用第三方库或C++开发时,接管内存统计有哪些困难
c++开发redis module问题之在复杂的Redis模块中,特别是使用第三方库或C++开发时,接管内存统计有哪些困难
|
1月前
|
Java 开发工具 Android开发
Android经典面试题之开发中常见的内存泄漏,以及如何避免和防范
本文介绍Android开发中内存泄漏的概念及其危害,并列举了四种常见泄漏原因:静态变量持有Context、非静态内部类、资源未释放及监听器未注销。提供了具体代码示例和防范措施,如使用ApplicationContext、弱引用、适时释放资源及利用工具检测泄漏。通过遵循这些建议,开发者可以有效提高应用稳定性和性能。
34 0