MetaAppUE工程师面经
差不多30Min,面试官人还不错,问了些C++基础和项目的问题,算法就一题还挺简单。整个过程主要是被一些基础知识问住,都是些概念性的问题,不能侥幸好好准备啊。但是整体面试专业度不错,而且公司效率比较高,我刚面完HR就通知说进复试了,目前已经三面入职拿到Offer,整体感觉还可以,公司上班时间变成早9晚7,我自己是电子科大的,周围技术挺多牛人。祝福程序猿兄弟们早日成功拿offer,也可以帮助大家推推推~
一、野指针?
1.概念:
指针指向了一块随机的空间,不受程序控制。
2.野指针产生的原因:
①指针定义时未被初始化:指针在被定义的时候,如果程序不对其进行初始化的话,它会随机指向一个区域,因为任意指针变量(出了static修饰的指针)它的默认值都是随机的
②指针被释放时没有置空:我们在用malloc()开辟空间的时候,要检查返回值是否为空,如果为空,则开辟失败;如果不为空,则指针指向的是开辟的内存空间的首地址。指针指向的内存空间在用free()和delete释放后,如果程序员没有对其进行置空或者其他赋值操作的话,就会成为一个野指针
③指针操作超越变量作用域:不要返回指向栈内存的指针或者引用,因为栈内存在函数结束的时候会被释放。
3.野指针的危害:
问题:指针指向的内容已经无效了,而指针没有被置空,解引用一个非空的无效指针是一个未被定义的行为,也就是说不一定导致错误,野指针被定位到是哪里出现问题,在哪里指针就失效了,不好查找错误的原因。
4.规避方法:
①初始化指针的时候将其置为nullptr,之后对其操作。
②释放指针的时候将其置为nullptr。
二、智能指针?
动态内存管理经常会出现两种问题:一种是忘记释放内存,会造成内存泄漏;一种是尚有指针引用内存的情况下就释放了它,就会产生引用非法内存的指针。
为了更加容易(更加安全)的使用动态内存,引入了智能指针的概念。智能指针的行为类似常规指针,重要的区别是它负责自动释放所指向的对象。标准库提供的两种智能指针的区别在于管理底层指针的方法不同,shared_ptr允许多个指针指向同一个对象,unique_ptr则“独占”所指向的对象。标准库还定义了一种名为weak_ptr的伴随类,它是一种弱引用,指向shared_ptr所管理的对象,这三种智能指针都定义在memory头文件中。
三、内存类型?
栈:是分配给函数局部变量的存储单元,函数结束后,该变量的存储单元自动释放,效率高,分配的空间有限。
堆:由new创建,由delete释放的动态内存单元。如果用户不释放该内存,程序结束时,系统会自动回收。
自由存储区:由new创建,由delete释放的动态内存单元,与堆类似。
全局(静态)存储区:全局变量和静态变量占一块内存空间。
常量存储区:存储常量,内容不允许更改。
四、堆和栈的效率?
堆相对于栈,效率低,多次分配(malloc/new)容易产生碎片,使用时最好结合相关操作系统(Linux、Windows、RTOS )使用,因为系统针对内存管理有专门的优化算法,减少内存碎片。堆虽然有一定的缺点,但其最大的优点是使用灵活,而且堆容量大,一般需要申请比较大的内存块时,都会从堆中申请,比如申请4K字节的数组。
以上,栈的效率比堆高
五、内存泄漏
类型:
①堆内存泄漏。在内存中程序员手动分配的一块内存,malloc\realloc\new。完成相关操作后,没有调用相对应的free\delete释放掉内存,这时这块内存就会常驻内存,造成堆内存泄漏
②系统资源泄漏。分配给程序使用的资源没有使用相应函数释放,如bitmap\handle\socket.
排查:
①BoundsChecker,定位运行时发生的各种错误
②调试运行DEBUG版程序,运用以下技术:CRT(C run-time libraries)、运行时函数调用堆栈、内存泄漏时提示的内存分配序号(集成开发环境OUTPUT窗口),综合分析内存泄漏的原因,排除内存泄漏。
③linux工具之检测内存泄漏-valgrind,功能强大,不仅仅是内存泄漏检测工具。
解决:
智能指针。因为智能指针可以自动删除分配的内存。智能指针和普通指针类似,只是不需要手动释放指针,而是通过智能指针自己管理内存的释放。
六、引用和指针?
指针保存的是指向对象的地址,引用相当于变量的别名
引用在定义的时候必须初始化,指针没有这个要求
指针可以改变地址,引用必须从一而终
不存在空引用,但是存在空指针NULL,相对而言引用更加安全
引用的创建不会调用类的拷贝构造函数
七、线程和进程?
进程是资源(CPU、内存等)分配的基本单位,它是程序执行时的一个实例。程序运行时系统就会创建一个进程,并为它分配资源,然后把该进程放入进程就绪队列,进程调度器选中它的时候就会为它分配CPU时间,程序开始真正运行。
线程是程序执行时的最小单位,它是进程的一个执行流,是CPU调度和分派的基本单位,一个进程可以由很多个线程组成,线程间共享进程的所有资源,每个线程有自己的堆栈和局部变量。线程由CPU独立调度执行,在多CPU环境下就允许多个线程同时运行。同样多线程也可以实现并发操作,每个请求分配一个线程来处理。
八、线程同步通信?
https://www.cnblogs.com/yhlboke-1992/p/9315263.html
九、map和unordered_map区别?
map:红黑树实现,增删改复杂度O(logN)
unordered_map:哈希表实现,查找复杂度O(1)
十、设计模式?
https://www.runoob.com/design-pattern/design-pattern-tutorial.html
十一、手撕代码:最大栈
类比leetcode:155.最小栈
#春招##MetaApp#
一、野指针?
1.概念:
指针指向了一块随机的空间,不受程序控制。
2.野指针产生的原因:
①指针定义时未被初始化:指针在被定义的时候,如果程序不对其进行初始化的话,它会随机指向一个区域,因为任意指针变量(出了static修饰的指针)它的默认值都是随机的
②指针被释放时没有置空:我们在用malloc()开辟空间的时候,要检查返回值是否为空,如果为空,则开辟失败;如果不为空,则指针指向的是开辟的内存空间的首地址。指针指向的内存空间在用free()和delete释放后,如果程序员没有对其进行置空或者其他赋值操作的话,就会成为一个野指针
③指针操作超越变量作用域:不要返回指向栈内存的指针或者引用,因为栈内存在函数结束的时候会被释放。
3.野指针的危害:
问题:指针指向的内容已经无效了,而指针没有被置空,解引用一个非空的无效指针是一个未被定义的行为,也就是说不一定导致错误,野指针被定位到是哪里出现问题,在哪里指针就失效了,不好查找错误的原因。
4.规避方法:
①初始化指针的时候将其置为nullptr,之后对其操作。
②释放指针的时候将其置为nullptr。
二、智能指针?
动态内存管理经常会出现两种问题:一种是忘记释放内存,会造成内存泄漏;一种是尚有指针引用内存的情况下就释放了它,就会产生引用非法内存的指针。
为了更加容易(更加安全)的使用动态内存,引入了智能指针的概念。智能指针的行为类似常规指针,重要的区别是它负责自动释放所指向的对象。标准库提供的两种智能指针的区别在于管理底层指针的方法不同,shared_ptr允许多个指针指向同一个对象,unique_ptr则“独占”所指向的对象。标准库还定义了一种名为weak_ptr的伴随类,它是一种弱引用,指向shared_ptr所管理的对象,这三种智能指针都定义在memory头文件中。
三、内存类型?
栈:是分配给函数局部变量的存储单元,函数结束后,该变量的存储单元自动释放,效率高,分配的空间有限。
堆:由new创建,由delete释放的动态内存单元。如果用户不释放该内存,程序结束时,系统会自动回收。
自由存储区:由new创建,由delete释放的动态内存单元,与堆类似。
全局(静态)存储区:全局变量和静态变量占一块内存空间。
常量存储区:存储常量,内容不允许更改。
四、堆和栈的效率?
堆相对于栈,效率低,多次分配(malloc/new)容易产生碎片,使用时最好结合相关操作系统(Linux、Windows、RTOS )使用,因为系统针对内存管理有专门的优化算法,减少内存碎片。堆虽然有一定的缺点,但其最大的优点是使用灵活,而且堆容量大,一般需要申请比较大的内存块时,都会从堆中申请,比如申请4K字节的数组。
以上,栈的效率比堆高
五、内存泄漏
类型:
①堆内存泄漏。在内存中程序员手动分配的一块内存,malloc\realloc\new。完成相关操作后,没有调用相对应的free\delete释放掉内存,这时这块内存就会常驻内存,造成堆内存泄漏
②系统资源泄漏。分配给程序使用的资源没有使用相应函数释放,如bitmap\handle\socket.
排查:
①BoundsChecker,定位运行时发生的各种错误
②调试运行DEBUG版程序,运用以下技术:CRT(C run-time libraries)、运行时函数调用堆栈、内存泄漏时提示的内存分配序号(集成开发环境OUTPUT窗口),综合分析内存泄漏的原因,排除内存泄漏。
③linux工具之检测内存泄漏-valgrind,功能强大,不仅仅是内存泄漏检测工具。
解决:
智能指针。因为智能指针可以自动删除分配的内存。智能指针和普通指针类似,只是不需要手动释放指针,而是通过智能指针自己管理内存的释放。
六、引用和指针?
指针保存的是指向对象的地址,引用相当于变量的别名
引用在定义的时候必须初始化,指针没有这个要求
指针可以改变地址,引用必须从一而终
不存在空引用,但是存在空指针NULL,相对而言引用更加安全
引用的创建不会调用类的拷贝构造函数
七、线程和进程?
进程是资源(CPU、内存等)分配的基本单位,它是程序执行时的一个实例。程序运行时系统就会创建一个进程,并为它分配资源,然后把该进程放入进程就绪队列,进程调度器选中它的时候就会为它分配CPU时间,程序开始真正运行。
线程是程序执行时的最小单位,它是进程的一个执行流,是CPU调度和分派的基本单位,一个进程可以由很多个线程组成,线程间共享进程的所有资源,每个线程有自己的堆栈和局部变量。线程由CPU独立调度执行,在多CPU环境下就允许多个线程同时运行。同样多线程也可以实现并发操作,每个请求分配一个线程来处理。
八、线程同步通信?
https://www.cnblogs.com/yhlboke-1992/p/9315263.html
九、map和unordered_map区别?
map:红黑树实现,增删改复杂度O(logN)
unordered_map:哈希表实现,查找复杂度O(1)
十、设计模式?
https://www.runoob.com/design-pattern/design-pattern-tutorial.html
十一、手撕代码:最大栈
类比leetcode:155.最小栈
#春招##MetaApp#