面经整理第三天(07.20)

编程入门 行业动态 更新时间:2024-10-23 21:37:23

面经整理第三天(07.20)

面经整理第三天(07.20)

面经整理

C++面试宝典中的面试题

!!!!这是用来背的不是用来看的!!不能草率复制粘贴

1.数组和链表的内存存储和插入

数组占用连续的内存空间,链表可以使用不连续的内存空间。数组插入可以直接插入到相应位置,但是需要从后往前进行移位,链表需要从头结点遍历到相应位置才可以插入,之后的元素不需要移位

2.include时,“”和<>的区别

#include<>:默认从系统库目录里查找头文件
#include" ":默认先从项目当前目录查找头文件,如果找不到,再从系统库目录里查找头文件

3.计算机内存只有1M,有一个文件1G,怎么排序

使用归并排序,每1M文件进行排序,然后对这,1024个文件进行排序

4.不用pow实现计算m的n次幂,时间复杂度

快速幂:将n转换二进制数,然后进行计算,时间复杂度为0(logn)

5.文件输入时,撤销键应该用什么数据结构实现

先入后出,栈

6.请你说一说TCP与UDP的区别

1.TCP是面向连接基于字节流的传输协议,UDP是面向无连接的基于数据包的不可靠传输协议
2.TCP具有一系列的措施来保证传输的可靠性,比如确认应答机制,滑动窗口机制,快速重传机制,拥塞避免机制。UDP只是尽最大努力交付,并不保证数据传输的可靠性。
3.TCP是面向连接的,因此一个TCP连接只能支持端到端的连接,并且是全双工通讯,UDP支持一对一、一对多、多对多的通信方式。
4.TCP的首部开销大20字节,UDP首部开销小8个字节。
5.TCP具有复杂的机制,因此具有可靠但速度慢、效率低、占用系统资源高的缺点。UCP不可靠但是速度快。

7.请你说说TCP三次握手四次挥手的过程

三次握手:
1.首先客户端主动建立连接请求,发送一个报文段,将报文段的SYN标志位置为1,随机产生一个初始序号seq1。
2.服务器接受连接请求,如果同意建立连接,将SYN,ACK标志位置为1,随机产生一个随机序号seq2,确认序号seq1+1;
3.客户端收到服务器的应答之后,发出最后的确认,将ACK置为1,确认需要为seq2+1发送给服务端。此时tcp连接建立成功。

说一下,SYN=1的报文段不可以携带数据,但是需要消耗掉一个需要,确认序号的意思是下一个要接收的序号,ACK置为1的报文段可以携带数据,但是如果不携带数据就不会消耗序号

四次挥手:
1.客户端发送连接释放报文,将FIN标志位置为1,此时序号为seq,也就是前面传输的报文段中最后一个字节的序号加一。
2.服务器收到报文段后,将ACK置为1,确认序号置为seq+1,序号为seq2,seq2为已经发送的数据段的最后一个序号+1,表示同意断开连接。
此时TCP连接处于一个半关闭的状态。
3.服务器没有数据要发送时,也会发送连接释放报文,将FIN标志位置为1,确认序号置为seq+1,序号为w。
4.客户端收到服务器的连接释放请求也必须发出确认,在确认报文段中将ACK置为1,确认需要ack为w+1,需要为seq+1;
这时候连接并没有立刻断开,等到2倍msl(最大报文段寿命)之后,连接才会释放,

8.说一说GET和POST的区别

1.get主要用来获取数据,post主要用来提交数据。
2.get请求的参数有最大长度限制,大小为2048字节,post请求没有最大长度限制。
3.get请求只支持url编码方式,post请求没有限制。
4.get请求的参数数据类型只接受ASCII字节,post没有限制。
5.get请求会保存在浏览器记录中,并且会被浏览器主要缓存,而post不会。

9.简述一下C++多态

1.C++多态分为静态多态和动态多态,静态多态指的是函数重载或函数模板,动态多态是用虚函数和虚函数表实现的。
2.静态多态在程序编译时期就会实现绑定,而动态多态要在程序运行时才会绑定。
3.动态多态是在程序运行时期根据基类的引用(指针)指向的对象来确定自己应该调用哪一个类的虚函数。当父类指针(或引用)指向父类对象时,就调用父类的虚函数,当父类指针(或引用)指向子类的对象时,就调用子类的虚函数。
4.动态多态的实现原理:当一个类中定义了虚函数,那个编译器会自动为其生成一个虚函数表,来用存储虚函数指针。当子类继承父类时,也会继承这样的一个虚函数表,当子类重写父类的虚函数时,虚函数表中函数的入口地址就会被改写。当多态调用时,会根据这个对象所在类的虚函数表中查找被调用的函数,从而找到函数的入口地址。

10.请你介绍一下死锁,死锁产生的必要条件,产生的原因,如何预防死锁。

死锁:两个或两个以上的进程因互相争夺资源而造成的一种互相等待的现象,若没有外力影响,他们将一直等待下去,不会退出。
死锁产生的必要条件:
1.互斥条件:一段时间内资源只能被一个进程所访问。
2.请求和保持条件:进程已经保持了一个资源,但是又提出了新的资源请求。
3.不可剥夺条件:进程已经拥有的资源在没有使用完之前不可剥夺
4.环路等待条件:存在一个资源的环形链。
产生死锁的原因:进程间的无序推进
如何预防死锁:实现有序资源分配,使用银行家算法。

11.请你说一说mysql索引,以及他们的好处和坏处

mysql索引主要有:普通索引、唯一索引、主键索引、外键索引、复合索引这几种。
索引的好处是在查询时通过索引查询可以大大提高查询效率。但是缺点是,索引的维护需要占用大量的空间,同时对数据库进行插入、更新、删除时,索引的维护也需要很大成本。并且也不是每次查询都能使用到索引,例如复合索引时,如果条件没有满足“最左前缀匹配”的原则,是不会走索引的。

12.简述一下什么是面向对象

首先看看面向过程:面向过程就是根据需求一步一步实现。每一个步骤都需要我们去实现和协调。
面向对象:认为程序是由一系列对象组成。面向对象有三个特性:封装、继承、多态。
封装:将事物的属性和行为都封装在一起,也就是C++的类,便于管理,提高代码复用性。事物的属性和行为就是类中的成员变量和成员函数。
继承:使类和类之间产生关系,提高代码复用性。
多态:根据调用方法对象的执行不同的函数。

13.简述一下面向对象的三大特征

1.封装:将事物的属性和行为都封装在一起,也就是C++的类,便于管理,提高代码复用性。事物的属性和行为就是类中的成员变量和成员函数。C++中通过private,protected,public三个关键字来控制成员变量和成员函数的访问权限。
2.继承:使类和类之间产生关系,提高代码复用性。并且继承是实现多态的基础
3.多态是在程序运行时期根据基类的引用(指针)指向的对象来确定自己应该调用哪一个类的虚函数。

14说一说进程间通信的方式有哪些

1.管道,管道本质上是内核维护的一块内存缓冲区,LINUX中通过pipe函数创建管道,生成两个文件描述符,分别对应着管道的读端和写端。管道只能用于具有血缘关系的进程间通信。命名管道会创建一个FIFO文件,不同的进程打开同一个FIFO文件就能进行进程间通信了。
2.信号,事件发生时对进程的一种通知机制,也被成为软件中断。
3.共享内存,共享内存允许多个进程共享一块物理内存区域。由于共享内存段在进程用户空间中,因此无需内核的介入,这种进程间通信的方式是最快的。
4.内存映射:将磁盘文件的数据映射到内存中,通过对内存的修改就能修改磁盘文件了
5.信号量:主要用来解决线程或进程间并发执行时的线程同步问题。
6.socket套接字:主要用来解决网络中不同主机上的应用进程之间的相互通信,提供应用层进程利用网络协议进行交换数据的机制。

15.说一说进程和线程的区别

1.进程有自己独立的地址空间,线程没有自己独立的地址空间,只有自己的堆栈和局部变量。
2.进程间上下文切换耗费资源大,线程间上下文切换耗费小,进程的并发性较低,线程的并发性较高。
3.每一个独立的进程都有一个程序运行的入口,而线程不能独立执行,必须依附于进程。
4.一个进程崩溃并不会对其他的进程造成影响,一个线程崩溃整个进程都会崩溃。

16.说一说epoll的基本原理

1.epoll_create会在内核中创建一个epoll对象,这个结构体有两个重要的数据结构,一个是用来存储待检测文件描述符的红黑树,另外一个是就绪列表。
2.epoll_ctrl可以向这个epoll对象中添加、删除、修改要检测的文件描述符
3.epoll_wt()可以让内核去检测事件,并将就绪事件放回到就绪列表中返回。
epoll有两种工作模式:
1.水平触发模式,内核检测到一个文件描述符就绪之后,会通知,当不做任何操作,还会继续通知这个已就绪的文件描述符
2.边沿触发模式,内核检测到一个文件描述符就绪后,只会通知一次。
边沿触发模式在很大程度上减少了epoll事件重复触发的次数,效率更高。

17.浏览器从输入URL到页面显示内容,中间发生了什么

1.浏览器根据属于的URL进行DNS解析,根据DNS解析结果得到服务器的IP地址。
2.通过IP地址找到服务器,通过TCP三次握手建立连接
3.浏览器发出HTTP请求,
4.服务器处理并返回应答。
5.浏览器对页面进行渲染。

在浏览器发出HTTP请求时,会查看web缓存。
1.浏览器访问web缓存服务器
2.web缓存中没有,web缓存浏览器请求源服务器,获取数据。
3.web缓存中有,如果是强制缓存且在有效期内,直接返回。如果是协商缓存,向源服务器请求资源是否更新过。

18.HTTP状态码及其含义

1xx:服务器已经接收了请求,
2xx:请求已经被服务器成功接收。
3xx:资源重定向
4xx:客户端的请求发生错误
5xx:服务端的响应出现错误。

301:永久重定向
302:临时重定向
304:资源没修改,用之前的缓存就行了。

404:服务器找不到请求的网页。

19.说一说Linux指令

top:查看操作系统相关信息,进程,CPU占用,内存信息
df:查看磁盘占用情况
free:查看内存占用情况
ps:查看进程情况
pwd:显示当前目录。

20.说一说http和https的区别

1.http默认端口号为80,https默认端口为443;
2.http只需要建立一次TCP连接,耗时1RRT,https需要建立两次TCP连接,耗时3RRT。
3.http明文传输,安全性低,https会对数据进行加密,安全性高。

21.说一说浅拷贝和深拷贝

浅拷贝:浅拷贝就是值拷贝,将源对象的值拷贝给目标对象,当对象中存在指针类型数据时,并且是在堆区创建的,使用浅拷贝仅仅是拷贝指针变量的值,此时源对象的指针和目标对象的指针指向同一块堆空间,当调用析构函数时,这块堆空间会被多次释放,默认的拷贝构造函数和赋值构造函数都是浅拷贝。

深拷贝:深拷贝在拷贝的时候会开辟出一块跟源对象大小相同的空间,然后将源对象里的内容拷贝到目标对象中去。这样指针变量指向不同的内存位置,调用析构函数时,不会出现重复释放同一块堆内存的错误。

22.说一说三种智能指针实现原理和使用场景,以及线程安全。

1.实现原理:说烂了。。。略
2.使用场景:
1)多个指针指向同一个对象:shared_ptr;
2)不需要多个指针指向同一个对象:unique_ptr
3)使用new分配内存,使用unique_ptr
4)使用new分配内存,并返回这个指向这个指针的地址,使用unique_ptr

3.线程安全:
shared_ptr:多线程传递使用时,引用计数线程安全。使用shared_ptr访问资源不是线程安全的,智能指针的拷贝也不是线程安全的。

23.tcp如何实现可靠传输

1.可靠传输:经过TCP传输的数据是没有差错、不会丢失、没有重复,并且按序到达的。

序列号:TCP会给每一个发送的数据包一个编号,接收方收到后根据编号排序。
检验和:检测数据是否发生改变
确认应答:接收方收到数据后会确认应答。
流量控制:TCP连接的每一方都有一个固定大小的缓冲空间,发送方只能发送窗口大小的数据。
拥塞控制:当网络阻塞时,减少发送。
超时重传:每一个数据包发送后,都会启动一个定时器,当不能及时收到确认信息,会重发这个报文段

24.介绍一个数据库的ACID

事务是由一系列SQL语句组成。
原子性:事务中的SQL语句要么全部成功,要么全部失败。
一致性:事务完成时,所有的数据保持一致的装填。
隔离性:保证事务在不受外部并发操作下的独立环境中运行
持久性:事务一旦提交,对数据库的改变是永久的。

25.说一说进程有多少种状态,如何转换。

进程有五种状态:创建、就绪、运行、阻塞、终止。
创建态:获取系统资源,创建进程管理块,完成资源分配
就绪态:万事具备,只欠CPU
运行态:获得CPU,被系统调度
阻塞态:运行期间,缺少资源
终止态:进程结束。

26.说一说select的原理和缺点

select是一种IO多路复用的技术。
1.首先会构造一个关于文件描述符的列表,将要监听的文件描述符添加到该列表中,这个列表的数据类型是一个整型数组,总共为1024个比特位,每一个比特位代表一个文件描述符的状态,0代表不检测对应文件描述符的状态,1表示检测对应文件描述符的状态。

2.调用select,监听列表中的文件描述符,0表示没有检测到事件,1表示有事件发生。对文件描述符的检测是通过内核完成的。

3.select返回时,会告诉进程有多少个描述符要进行IO操作,遍历文件描述符列表。

缺点:
1.每次调用select,都需要把存放文件描述符的列表从用户态拷贝到内核态,返回时,需要将列表从内核态拷贝到用户天。
2.每次调用select都需要遍历列表然后进行检测,函数返回后,也需要遍历列表然后进行判断。
3.select支持的文件描述符数量太少。

27.请你介绍一个IO多路复用

28.说一说new的实现原理,new和malloc的区别

1.new是操作符,可以被重载,malloc是函数,不能被重载。
2.new分配内存时,如果复杂类型,先调用operator new().然后在分配的内存上调用构造函数。malloc不会。
3.使用new分配内存时,无需指定内存块的大小,编译器会根据类型信息自行计算,malloc需要显式地指定分配内存的大小。
4.new分配成功后会返回对应类型的指针,malloc分配成功后返回void*
5.new分配失败后抛异常,malloc分配失败后返回NULL。
6.new分配内存后,不能扩充,malloc分配内存后,可以通过realloc进行内存扩充。

29.说一说STL常见容器

1.顺序容器:容器不是排序的,vector,deque,list。
2.关联式容器:元素是排序的,查找时具有非常好的性能,通常是用平衡二叉树构建的,set,map。
3.容器适配器:封装了基本的容器,使之具备新的函数功能。stack,queue,priority_queue

30.STL容器用过哪些,查找的时间复杂度

vector:一维数组实现,元素在内存中顺序存放,插入O(n),查看O(1),删除O(N)
list:双向链表
插入O(1),查看O(N),删除O(1)
deque:双端队列,
插入O(N),查看O(1),删除O(N)
map,set,红黑树实现
插入O(logN),查看O(logn),删除O(logn)
unordered_map,unordered_set
插入O(1),查看O(1),删除O(1)

31说一说TIME_WT

产生TIME_WT的原因是为了TCP全双工连接的可靠释放。当主动放弃连接释放的一方 最后发送的ACK确认数据包在网络中丢失时,由于超时重传机制,被动关闭连接的一方会重新发送FIN包,在FIN包到达主动关闭连接的一方之前,主动关闭连接的一方需要维持这条连接。
主动连接方收到FIN后,重新发送ACK确认数据包,然后经过2MSL时间后进行CLOASE状态。

32说一说拥塞控制机制

拥塞控制就是为了防止过多的数据进入网络当中。
拥塞控制算法有以下四种:慢启动、拥塞避免、快重传、快恢复。
慢启动:开始时设置拥塞窗口大小为1 ,每收到一个确认应该就将拥塞窗口加倍。
快重传:当接收方每收到一个失序报文就发出重复
确认,发送方连续收到三个重复确认后,立刻发送相应序号的报文。
快恢复:当发送方连续收到三个重复确认后,就认为此时网络拥塞,此时将慢启动的门限值减半,然后进行拥塞避免。
拥塞避免:此时每收到一个确认应答拥塞窗口加一。

33.说说堆和栈的区别

1.栈是由编译器进行自动管理的,堆是由程序员手动分配和回收。
2.栈不会产生内存碎片,堆会产生大量内存碎片
3.栈的生长方向是沿内存地址减少的方向。堆的生长方向是沿内存地址增加的方向。
4.栈是系统提供的一种数据结构,并且有专门的寄存器存放栈的地址,因此效率很高,堆是由C++函数提供的,当没有足够大小的空间(内存碎片过多)时,还需要调用系统功能增加程序数据段的内存空间,这样就有机会分到足够大小的内存。

34.说说线程和协程的区别

35.说一说TCP/IP五层模型

1.五层协议体系就是计算机网络中交换数据所需要遵循的规则。
应用层:定义了应用进程间通信和交互的规则,常见的应用层协议有万维网应用的HTTP协议,电子邮件的SMTP协议,文件传送的FTP协议。
传输层:负责为两个计算机中进程之间提供的一种数据传输服务,主要协议有UDP,TCP
网络层:负责为网络上不同的主机提供通信服务。网络层将传输层产生的报文段封装成包进行传送。
主要协议有:ICMP,IGMP,IP,ARP,RARP。
数据链路层:链路层将网络层交付的数据报封装成帧,然后传送。
物理层:通过比特流来实现数据的传输。

36.TCP粘包问题

TCP粘包产生的原因:
1.TCP是基于字节流的,无法判断发送方发送报文的边界。
2.接收方接收数据的时候,多个数据包存储在连续的缓存中,在对数据包读取时无法确定数据包的大小,只能随意读。
3.若发送包发送数据包的长度和接收方读取数据包的长度不一致时,就会发生粘包。

解决办法:
1.采用定长的数据包
2.数据包的末尾加上\r\n标志,但是如果数据内容中有\r\n,就会发生错误。
3.在数据包的头部加上数据包的长度信息,数据包的头部设置为定长4字节,存储数据包的整体长度。

37.说一说滑动窗口

流量控制中的窗口会持续向前滑动,因此称为滑动窗口。整个报文段可以分为四组:已被确认的分组,已经发送但未被确认的分组,可以发送的分组,超出窗口长度待使用的分组。

38.说一说指针和引用的区别

1.指针是一种数据类型,引用只是变量的别名
2.指针可以为NULL,不初始化,引用在创建时必须初始化
3.指针的值在初始化之后还可以修改,引用在创建后不可修改。
4.sizeof指针得到的是指针变量本身的大小,sizeof引用得到的是所引用的那块内存的大小。
5.指针作为参数传递传递的是指针变量的值。
引用作为参数传递传递的是实参本身。

39.请说说单例设计模式。

单例类只能有一个实例。
单例类中私有化构造函数,拷贝构造函数,赋值函数,定义了一个私有的静态成员变量,提供了一个公共访问该静态成员变量的方法,返回该静态成员。
单例模式有两种:
1.懒汉式:获取该类的对象时才创建该类的实例
2.饿汉式:获取该类的对象之前就创建好该类的实例。

单例模式的优点:保证内存中只有一个实例,避免对资源的重复占用。
单例模式的缺点:扩展困难,不利于调试。

40.请你说说InnoDB的MVCC

41.简述一下C++的重载和重写

重载:函数名相同,但是函数参数列表不同。
重写:子类对父类的虚函数的重新实现。

42.说一说TCP和UDP的使用场景

UDP的优点是快,很多实时性高的场景中允许数据丢失,因此使用UDP协议更好,如语音、视频、游戏、广播。DNS和ARP协议也是使用UDP实现,快速获取IP地址和MAC地址。

TCP的优点是可靠交付,如浏览器向服务器获取资源,SMTP中都是使用TCP协议。

43说说DNS解析的过程以及DNS劫持

DNS解析过程:
1.请求本地缓存,查询host域名配置
2.查询本地DNS服务器
3.查询根域名服务器。根域名服务器返回顶级域名服务器。
4.查询顶级域名服务器,顶级域名服务器返回权威域名服务器
5.查询权威域名服务器,拿到ip地址,并将结果缓存在本地DNS服务器上。

DNS劫持:输入了百度的网址却进入了一个奇怪的网址,这种情况下就是攻击者修改了本地路由器中DNS地址。发生了DNS劫持现象。

----------------------分割线07.21第四天-------------------------------------------------

44.说一说虚函数的实现原理

虚函数的作用主要是为了实现动态多态。
动态多态:父类类型的指针或者引用指向子类的对象时,通过父类指针调用实际子类的成员函数。
实现原理:编译器在处理虚函数时,会为每一个对象添加一个虚函数指针,指向虚函数表,虚函数表存储的是类中虚函数的地址。如果子类中重写了虚函数,那么子类的虚函数表中相应函数的入口地址就是保存的是子类的虚函数地址。

45.请你讲讲B树和B+树

1.k阶B树,每个中间结点只存k-1个值,k个指针。
k阶B+树,B+树存k个值和k个指针
2.B树中所有结点都会存放关键字,B+树所有的关键字都在叶子结点
3.B+树的叶子结点是带有指针的,并且叶子结点本身按关键字从小到大顺序连接。

46.简单叙述一下GDB常见的调试命令

启动:gdb ./*out
退出:q
给程序设置参数/获取设置参数:set args 10 20
查看当前代码:
设置断点:b 行号/函数名/文件名/文件名:函数
查看断点:i b
删除断点:d 断点编号
设置端点无效:dis 断点编号
设置端点生效:ena 断点编号
设置条件断点:b 10 if i==5
运行GDB程序:start(程序停在第一行) run(遇到断点才停) 继续运行
到下一个断点停:c/continue
向下执行一行代码(不会进入函数体):n/next
变量操作:p/print 变量名(打印变量值),ptype 变量名(打印变量类型)
向下单步调试(遇到函数进入函数体):s/step finish(跳出函数体)
查看当前调试环境中有多少个进程:info inferiors
切换到指定 ID 编号的进程对其进行调试:inferior id
set var 变量名=变量值 (循环中用的较多) until (跳出循环)

47.说一说 C++ 和 C 中 struct 的区别以及和 class 的区别

48.请你说说各数据类型 sizeof 是多少,sizeof 指针是多少,sizeof 原理

sizeof的结果其实是该数据类型的字节数。

49.为什么将析构函数设置成虚函数

虚析构函数的作用主要是为了内存泄漏。如果基类中的析构函数没有声明为虚函数,基类指针指向派生类对象时,当基类指针释放时不会调用派生类对象的析构函数,而是只调用基类的析构函数。

50.请你说说导致哈希冲突的原因和影响因素,哈希冲突的解决方法

哈希冲突的原因:通过哈希函数产生的哈希值是有限的,当数据过多,导致不同的数据经过哈希计算得到相同的值,就会产生哈希冲突。

解决哈希冲突的方法:
1.开放地址方法:一旦发生冲突就是寻找下一个空的空间。
2.链式地址法:每一个哈希表结点都有一个next指针。
3.建立公共溢出区:建立基本表和溢出表,一旦和基本表发生冲突,填入溢出表
4.再哈希法:当发生哈希冲突时,使用第二个哈希函数进行重新计算

51.TCP的流量控制

流量控制的目的就是让发送方的发送速率不要过快,让接收方来得及接收所有的数据。

客户端和服务器建立TCP连接的时候,客户端会告诉服务器自己的接受窗口大小,这时候服务器发送窗口的数据总大小不能超过客户端给出的窗口大小。

52.说一说malloc的实现原理

malloc()的实现原理:维护一个内存空闲链表,当申请内存空间时,搜索内存空闲链表,找到适配的空闲内存空间,然后将空间分割成两个内存块,一个变成分配块,一个变成新的空闲块。

53.说一说delete和free的区别

1.delete是操作符,free是函数
2.delete释放new出来的内存空间,free释放malloc出来的内存空间
3.delete会调用对象的析构函数,free不会调用。
4.delete前不会检查指针是否为NULL,free前需要检查释放的指针是否为NULL。

54.说一说进程调度算法

1.先来先服务:在就绪队列中选择存在时间最长的
2.短作业优先:从就绪队列中选择一个估计运行时间最短的
3.优先级调度:在就绪队列中选择优先级最高的
4.高响应比调度:先来先服务和短作业优先的平衡,同时考虑每个进程的等待时间和估计运行时间
5.时间片轮转:每个进程一个时间片,用完就停止,放到就绪队列的尾部
6.多级反馈队列调度:时间片轮转和优先级的平衡,动态调整进程优先级和时间片大小。

55.说说ARP协议,协议是怎么实现的,怎么找到MAC地址的

56.什么是内存泄漏,如何检测

程序动态分配的堆内存未释放。
如何检测:
1.养成良好的编码习惯,及时释放内存
2.静态分析技术或源代码插装技术。

57.说一说线程的通信方式

同一个进程间的线程共享同一块全局内存区域,包括初始化数据段、未初始化数据段、堆内存段等。因此对于线程之间的通信可以直接使用全局变量或堆上的变量。不过需要考虑到线程的同步和互斥。

用到的技术有:
1.信号:pthread_kill()向线程发出信号
2.互斥锁:确保同一时间内只有一个线程可以访问共享资源
3.读写锁:读模式共享,写模式互斥
4.自旋锁:锁受阻时不阻塞,不断轮询查看是否能获得该锁。
5.信号量:整数计数器,用来表示共享资源的个数,当信号量大于0的时候才能访问信号量所代表的资源。

58.说一说虚拟内存与物理内存

物理内存:在没有虚拟内存概念的时候程序寻址方式就是物理寻址。程序寻址范围取决于CPU地址线条数。32位平台下,寻址范围就是2^32也就是4G,如果没有虚拟内存,每开启一个进程都需要分配4G物理内存,造成内存不够。
由于指令都是直接访问物理地址的,因此一个进程可以修改另一个进程的数据,不安全。
虚拟内存:让应用程序认为它拥有连续可用的内存。

59.说说分段和分页

分段:将用户程序地址空间根据程序逻辑分成不同的段。
分页:将用户程序地址空间划分为固定大小的区域,同时将内存空间划分为若干个物理块,页和块的大小相等。能够很好地解决内存碎片的问题。
段页式:先将用户程序分成若干个段,再把每个段分成若干个页,并为每一个段赋予一个段名,同时配置段表和页表,段表查到页表始址,然后通过页表找到页帧号,最终形成物理地址

60.数据库为什么不用红黑树而用 B+ 树

红黑树本质还是二叉树,在数据量非常大时,二叉树的深度还是会非常大,同时数据是存在磁盘上的,访问需要进行磁盘IO,导致效率较低。B+树是多叉的,同时B+树增加了叶子结点间的连接,能保证范围查询时找到起点和终点后快速取出需要的数据

61.请你说说乐观锁和悲观锁

乐观锁:乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是更新的时候会判断数据是否更改,适用于多读的场景。
悲观锁:悲观,每次去拿数据的时候都认为别人会修改,因此每次拿数据的时候都会上锁。

62,什么是孤儿进程,什么是僵尸进程,如何解决僵尸进程

孤儿进程:父进程退出后,子进程还未退出,子进程就会变成孤儿进程。孤儿进程会被init进程收养。
僵尸进程:子进程退出后,父进程并没有调用wait和waitpid来回收子进程的进程描述符,此时子进程就会变成僵尸进程。
解决办法:
1.及时回收
2.子进程退出时,内核会给父进程发送一个SIGCHID信号,建立一个捕获SIGCHID信号的信号处理函数,然后在函数体内调用wait和waitpid。

63.说一说CLOSE_WT

CLOSE_WT对方已经关闭了连接但是自身还未提出关闭连接,因此进入CLOSE_WT状态。

64.说一说static关键字

65说一说什么是野指针

野指针:指向无效区域的指针。
产生原因:
1.指针变量未初始化
2.指针释放后未置空,指针指向的内存被释放,但是指针的值还在,对指针进行解引用结果不可知。
3.指针超过了作用于,例如函数中返回了局部变量的地址。
如果避免野指针:
1.指针变量一定要初始化。
2.指针释放后置空。

66.说一说const和define的区别

1.const生效于编译期,define生效于预处理阶段。
2.const有数据类型,define不会进行类型检查
3.const在静态存储区分配空间,define不分配内存。

67.说一说unique_ptr的实现原理和使用场景

1.独占所有权。只有一个智能指针可以拥有该对象。
2.拷贝构造和拷贝赋值声明为delete。
使用场景:
1.程序不需要多个指向同一个对象的指针。
2.new []分配内存
3.函数中用new分配内存,返回指向该内存的指针,将返回类型声明为unique_ptr;

68.说一说大端和小端,如何判断

大端:高位存储在低地址,低位存储在高地址。
小端:高位存储在高地址,低位存储在低地址。

69.请你说说共享内存

1.共享内存是一种进程间通信的方式,共享内存为一块物理内存,所有进程都可以访问共享内存。
2.访问共享内存并不需要系统调用,避免了数据不必要的复制。
3.使用共享内存时需要保证进程间同步。

70.请你说一说聚集索引和非聚集索引

1.聚类索引是通过主键创建的一颗B+树,索引的叶子结点存放的是表中的数据内容。
2.非聚集索引的叶子结点存放的是主键值,如果使用非聚集索引查询需要进行回表查询。

71.请你说说C++的内存管理

C++的内存分区主要分为:代码区,未初始化数据段,已初始化数据段,栈区,堆区

72.什么是纯虚函数,有什么作用。

在基类中不能对虚函数给出具体有意义的实现,就把虚函数定义为纯虚函数。剩下的留给派生类自行重写虚函数。
如果一个类中有纯虚函数,那么这个类也被成为抽象类,不能实例化对象。

73.请你说说 deque 的实现原理

74.请你说说写时拷贝

写的时候才分配内存,fork创建子进程后,并不会立刻复制一个地址空间给子进程,而是让父子进程共享同一个地址空间,只在需要写入的时候才会复制地址空间。

75.请你说说互斥锁和自旋锁

互斥锁:用来保护临界区的一种方式,同一时间只能有一个线程拥有锁。
自旋锁:在获得锁之前一直处理自旋阻塞的状态。

76.说说extern的作用,extern变量在哪个数据段,为什么要用extern C

extern 置于变量声明和函数声明之前,便是变量和函数在别的文件中定义。
extern “C”:保证C++能够正常调用C语言代码,表示这部分代码按照C语言编译。比如C++编译函数的时候会将函数的参数类型也加到编译后的代码中,但是C不会。

77.说说C++中的内存对齐

什么是内存对齐:
内存空间都是按照字节划分的,理论上对任何类型的变量的访问可以从任何地址开始,但是实际上操作系统对基本数据类型在内存中存放的位置有限制,要求数据的首地址的值是4或者8的倍数。

内存对齐的原因:
1.平台原因:不是所有的硬件平台都能访问任意地址上的任意数据。
2.性能原因:对于未对齐的内存,处理器需要两次访问内存,对于已经对齐的内存,处理器只需要一次访问。
3.内存对齐的规则 #pargma pack(n)指定对齐系数。

78.set的实现原理

底层使用红黑树来实现,对于set来说,插入删除效率都很高。因此二叉树的插入删除元素不需要进行内存拷贝和内存移动。

79.说说智能指针有没有内存泄漏的情况

当两个类对象各自有一个share_ptr指向对方时,就会造成循环引用,引用计数失效,造成内存泄漏

使用弱引用指针weak_ptr,weak_ptr的构造不会修改引用计数的值,不控制对象声明周期,因此不会造成无法释放内存的情况

80.说说左值、右值、左值引用、右值引用的使用场景

1.左值,可以取地址,有名字的
2.右值,不能取地址,没有名字
3.左值引用:对左值进行引用,对左值起一个别名
4.右值引用:对右值进行引用,引用可指向右值,右值引用&&,使用场景,移动语义,完美转发。

81.说说动态库静态库的区别和优缺点

静态库的链接:将函数库的数据在编译时整合进目标代码
动态库的链接:程序执行到哪个函数链接到哪个库。

优缺点:
静态库:发布程序时无需额外提供静态库,运行速度快,但是生成的可执行文件大,消耗内存,如果使用的静态库发生改变,程序必须重新编译
动态库:节省内存,动态库的改变不影响程序的使用,但是发布程序的时候需要提供相应的动态库

82.请你说说条件变量

条件变量总是和互斥锁一起使用,使用条件变量可以以原子的方式阻塞线程,直到某个特定的条件为真,则会唤醒阻塞在条件变量上的线程。

83.数据库的索引结构,为什么不适用哈希表

哈希表的查询效率很高,但是要求将所有的数据都载入内存中,而数据库一般存储的数据量都非常大,全部载入内存上基本不可能。
b+树可以分段加载需要的结点数据,在内存有限的前提条件下,极大提高查询效率

84.C++中四种类型转换

static_cast:静态转换,没有动态类型检查,用于基本数据类型的转换。
上行转换:派生类指针或是引用转换为基类:是安全的
下行转换:基类指针转换为派生类指针:不安全的

dynamic_cast:动态类型转换,可用于派生类指针和基类指针之间的类型转换,具有类型检查。

const_cast:常量转换,将常量指针转化为非常量指针,常量引用转换为非常量引用。

reinterpret_cast:不安全,别用

85.weak_ptr如何解决shared_ptr的循环引用问题

weak_ptr指向一个由shared_ptr管理的对象,但是不影响所指对象的生命周期,无法解引用和获取指针,只能通过lock成员函数获取对应的shared_ptr,不论是否在weak_ptr指向,一旦最后一个指向对象的shared_ptr被销毁,对象就会被销毁。

86.请你说说https

在http的基础之上加入了TLS(安全套接层)协议,在数据的传输过程中,会对传输的数据进行加密。并且需要证书认证客户端访问的是正确的服务器。

87TCP超时重传机制,时间是多少?

TCP协议要求发送端每发送一个报文段,就启动一个定时器并等待确认信息,若在定时器超时之前数据未能被确认,tcp就认为报文段中的数据已丢失或损坏,需要对报文段中的数据进行重传。

TCP协议使用自适应算法来适应互联网分组传输时延的变化,监视每一个TCP时延,由此推断出合适的超时时间。

88.说一说const的用法

1.修饰变量,变量不可修改

const int a;	//常量,不可修改
const int *p;	//常量指针,指针指向的内容是常量
int *const p;	//指针常量,指针不可修改
void foo(const int * p); //形参在函数内部不可修改
void fun() const;//不能修改成员变量

89.C++引用

1.引用可以看成数据的一个别名。
2.在定义引用时必须进行初始化,一旦初始化不能再引用其他数据。
3.引用的本质是指针

90.说说内联函数和函数的区别,内联函数的作用

更多推荐

面经整理第三天(07.20)

本文发布于:2024-02-12 19:50:34,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1689186.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!