面试官:小伙子,说说C/C++是如何进行内存管理的?我:……
要努力,但不要着急,繁花锦簇,硕果累累,都需要过程!
目录
前言:
1.C/C++内存分布
2.C/C++动态内存管理方式
2.1C语言动态内存管理:
2.2C++语言动态内存管理:
2.3operator new和operator delete函数:
2.4new和delete的实现原理:
3.常见的面试题
总结:
前言:
本篇是主要介绍关于C语言和C++语言如何进行动态内存管理,动态内存管理不仅在语言学习的路上非常重要,而且也是在面试的时候面试官通常会问到的一个热点问题。
1.C/C++内存分布
在编译器上我们写完代码之后,代码会保存到文件中,当我们编译链接完成之后,会生成一个.exe的可执行程序,此时我们的代码会根据不同的类型保存到虚拟进程地址空间,如下图
1.C/C++中程序内存划分:
不同区域变量保存类型:
栈:局部变量,函数形参
堆区:malloc,calloc,realloc申请的空间
静态区:全局变量,static修饰的全局变量,static修饰的局部变量
代码段(常量区):字符常量等
2.内存区域分布练习:
int globalVar = 1; static int staticGlobalVar = 1; void Test() { static int staticVar = 1; int localVar = 1; int num1[10] = { 1, 2, 3, 4 }; char char2[] = "abcd"; const char* pChar3 = "abcd"; int* ptr1 = (int*)malloc(sizeof(int) * 4); int* ptr2 = (int*)calloc(4, sizeof(int)); int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4); free(ptr1); free(ptr3); }
2.C/C++动态内存管理方式
在C/C++中我们经常会向堆上申请空间,因为堆上的空间比较大,但是堆上申请的空间如果使用者自己不主动释放的时候就会造成内存泄漏,因此既好用又难用,成为面试官针对程序员对语言掌握情况而常问的问题
2.1C语言动态内存管理:
关于对C语言动态内存的介绍,前边已经介绍,详情请戳—>C语言动态内存详解
2.2C++语言动态内存管理:
C++通过两个操作符向堆上申请空间的:
new:向堆上申请空间
delete:释放申请的空间
int main() { //申请内存 int* p = new int; //释放内存 delete p; return 0; }
注:内置类型申请的内存空间默认不初始化
初始化的方式:
一次性申请一块大的空间:
C++中的new和delete与C语言的malloc和free在用法上并没有什么区别,对于内置类型效果相同,但是对于自定义类型,new和delete会调用构造函数和析构函数
class A { public: A(int a = 0) : _a(a) { cout << "A():" << this << endl; } ~A() { cout << "~A():" << this << endl; } private: int _a; }; int main() { A* p = new A; delete p; return 0; }
2.3operator new和operator delete函数:
new和delete是用户进行动态内存申请和释放的操作符,operator new 和operator delete是
系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间
new和delete底层调用:可以通过反汇编进行观察
而operator new和operator delete函数又调用的是malloc和free
2.4new和delete的实现原理:
内置类型:
如果申请的是内置类型的空间,new和malloc,delete和free基本类似,不同的地方是:
new/delete申请和释放的是单个元素的空间,new[]和delete[]申请的是连续空间,而且new在申请空间失败时会抛异常(后续解释),malloc会返回NULL。自定义类型:
new的原理
1. 调用operator new函数申请空间
2. 在申请的空间上执行构造函数,完成对象的构造
delete的原理
1. 在空间上执行析构函数,完成对象中资源的清理工作
2. 调用operator delete函数释放对象的空间
new T[N]的原理
1. 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对
象空间的申请
2. 在申请的空间上执行N次构造函数
delete[]的原理
1. 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理
2. 调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释
放空间
3.常见的面试题
1.malloc/free和new/delete的区别?
共同特点:
malloc/free和new/delete都是从堆上申请空间,使用完之后需要手动释放
不同点:
1.malloc和free是函数,new和delete是操作符;
2.对于自定义类型malloc申请的空间不会初始化,new申请的空间会调用构造函数进行初始化
3.malloc申请空间需要传递空间大小,new只需在后面跟上空间大小即可,如果是多个对象,只需在[]中指明对象的个数即可;
4.malloc的返回类型是void*,在使用的时候必须强转,new不需要;
5.malloc空间申请失败时返回NULL, new空间申请失败抛异常;
6.申请自定义类型的对象时malloc和free不会调用构造函数和析构函数对空间进行初始化,和对象资源的清理,new和delete会调用构造函数和析构函数完成对象的初始化和对象资源的清理
2.什么是内存泄漏,内存泄漏的危害是什么?
内存泄漏是指因为错误或疏忽造成程序未能释放已经不再使用内存的情况,内存泄漏并不是指内存在物理上的消失,而是应用程序在分配某块内存后,因为设计错误,失去了对该内存的控制,因而造成了内存的泄漏
内存泄漏的危害:长期运行的程序出现内存泄漏,会造成程序越来越卡,最终会出现卡死的现象
总结:
对内存的申请和使用是在学习的过程中必不可少的,但是在使用的时候,我们应该要学会正确的使用,防止造成内存泄漏等问题