蚂蚁OceanBase 一面面经C++之解答

原帖:https://www.nowcoder.com/feed/main/detail/34a2bc09b6e54494abb1767b3242e96e

1 网络七层/四层模型

2 路由器在哪一层?交换机在哪一层?(当时答错了)

路由器通常工作在网络层(第三层),主要负责将数据包从一个网络传输到另一个网络,通过选择最优路径来实现跨越不同网络的通信。

交换机通常工作在数据链路层(第二层),主要负责在局域网中转发数据包,根据目的MAC地址将数据包从一个接口转发到另一个接口。

3 数据链路层的协议(各层的协议后面再记一下)

  1. 以太网(Ethernet):是应用最广泛的局域网协议,常用于连接计算机、交换机、路由器等设备。
  2. 无线局域网协议(Wi-Fi):是一种无线局域网标准,可以在不需要物理连接的情况下提供高速数据传输。
  3. 点对点协议(PPP):是一种用于建立点对点连接的协议,常用于拨号上网和虚拟专用网络(VPN)等场景。
  4. 高级数据链路控制协议(HDLC):是一种同步的数据链路层协议,常用于广域网中传输数据。

4 mac地址的作用?是属于物理还是逻辑的?

MAC地址的作用是在局域网中标识和定位设备,使数据包能够正确地传输到目标设备。在数据链路层中,数据包的传输需要使用目标设备的MAC地址来进行寻址

MAC地址是属于物理地址,因为它是由设备的网卡硬件制造商预先设定的,是设备的固定属性,不能更改。

5 TCP/UDP在哪一层?两者区别?为什么要三次握手?为什么要四次挥手?

传输层

(1)TCP需要建立一对一稳定连接;UDP无连接

(2)TCP一对一;UDP可以一对一、一对多、多对多

(3)TCP可靠传输,序列号、确认应答、超时重传;UDP不保证可靠传输,尽最大努力交付

(4)TCP头部字节20字节;UDP8个字节

(5)TCP开销大;UDP灵活开销小

(6)TCP提供可靠的服务,适用于通讯质量要求高的场景;UDP传输效率高,适用于高速传输和实时性要求的场景。

不能两次

假如只进行两次握手,客户端发送连接请求后,会等待服务器端的应答。但是会出现的问题是,假如客户端的SYN迟迟没有到达服务器端,此时客户端超时后,会重新发送一次连接,假如重发的这次服务器端收到了,且应答客户端了,连接建立了。

但是建立后,第一个SYN也到达服务端了,这时服务端会认为这是一个新连接,会再给客户端发送一个ACK,这个ACK当然会被客户端丢弃。但是此时服务器端已经为这个连接分配资源了,而且服务器端会一直维持着这个资源,会造成资源浪费。

两次握手的问题在于服务器端不知道SYN的有效性,所以如果是三次握手,服务器端会等待客户端的第三次握手,如果第三次握手迟迟不来,服务器端就会释放相关资源

不能三次。

第二次挥手和第三次挥手不能合并在一起,这是因为第二次挥手后,服务器端可能还在传输数据,需要等待数据传输完毕后再进行第三次挥手。

6 I/O多路复用方式

  1. select:select是一种阻塞式I/O多路复用方式,它可以同时监视多个文件描述符的读写状态,并在有数据可读或可写时返回。它的缺点是单个进程能够监视的文件描述符数量受限于系统的最大文件描述符数量,而且每次调用select都需要将所有被监视的文件描述符集合从用户态复制到内核态,效率不高。
  2. poll:poll是一种与select类似的阻塞式I/O多路复用方式,可以同时监视多个文件描述符的读写状态,并在有数据可读或可写时返回。与select不同的是,poll没有文件描述符数量的限制,效率比select稍高一些。
  3. epoll:epoll是一种高效的I/O多路复用机制,它可以同时监视多个文件描述符的读写状态,并在有数据可读或可写时返回。与select和poll不同的是,epoll采用了事件驱动的方式,只会返回发生变化的文件描述符,减少了内核态和用户态的数据拷贝次数,效率更高。

7 进程和线程的区别

(1)一个线程从属于一个进程;一个进程可以包含多个线程。

(2)一个线程意外死亡,可能导致进程挂掉;一个进程挂掉,不会影响其他进程。

(3)进程是系统资源调度的最小单位;线程CPU调度的最小单位。

(4)进程系统开销显著大于线程开销;线程需要的系统资源更少。

(5)进程在执行时拥有独立的内存单元,多个线程共享进程的内存,如代码段、数据段、扩展段;但每个线程拥有自己的栈段和寄存器组。

(6)进程切换时需要刷新TLB并获取新的地址空间,然后切换硬件上下文和内核栈,线程切换时只需要切换硬件上下文和内核栈。

(7)通信方式不一样。

(8)进程适应于多核、多机分布;线程适用于多核

8 了解死锁么?死锁怎么产生的?怎么避免死锁?

  1. 死锁: 是指多个进程在执行过程中,因争夺资源而造成了互相等待。此时系统产生了死锁。比如两只羊过独木桥,若两只羊互不相让,争着过桥,就产生死锁。
  2. 产生的条件:死锁发生有四个必要条件: (1)互斥条件:进程对所分配到的资源不允许其他进程访问,若其他进程访问,只能等待,直到进程使用完成后释放该资源;(2)请求保持条件:进程获得一定资源后,又对其他资源发出请求,但该资源被其他进程占有,此时请求阻塞,而且该进程不会释放自己已经占有的资源;(3)不可剥夺条件:进程已获得的资源,只能自己释放,不可剥夺;(4)环路等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
  3. 如何解决:(1)资源一次性分配,从而解决请求保持的问题(2)可剥夺资源:当进程新的资源未得到满足时,释放已有的资源;(3)资源有序分配:资源按序号递增,进程请求按递增请求,释放则相反。

9 了解虚拟内存么?

  1. 虚拟内存:操作系统为每一个进程分配一个独立的地址空间,却是虚拟内存。虚拟内存与物理内存存在映射关系,通过页表寻址完成虚拟地址和物理地址的转换。
  2. 为什么要用虚拟内存:因为早期的内存分配方法存在以下问题:(1)进程地址空间不隔离。会导致数据被随意修改。(2)内存使用效率低。(3)程序运行的地址不确定。操作系统随机为进程分配内存空间,所以程序运行的地址是不确定的。
  3. 使用虚拟内存的好处:(1)扩大地址空间。每个进程独占一个4G空间,虽然真实物理内存没那么多。(2)内存保护:防止不同进程对物理内存的争夺和践踏,可以对特定内存地址提供写保护,防止恶意篡改。(3)可以实现内存共享,方便进程通信。(4)可以避免内存碎片,虽然物理内存可能不连续,但映射到虚拟内存上可以连续。
  4. 使用虚拟内存的缺点:(1)虚拟内存需要额外构建数据结构,占用空间。(2)虚拟地址到物理地址的转换,增加了执行时间。(3)页面换入换出耗时。(4)一页如果只有一部分数据,浪费内存。

10 c++中i++ 和++i的区别?++i快还是i++更快呢?两个float类型如何判断相等?

  1. 赋值顺序不同:++ i 是先加后赋值;i ++ 是先赋值后加;++i和i++都是分两步完成的。
  2. 效率不同:后置++执行速度比前置的慢。
  3. i++ 不能作为左值,而++i 可以
  4. 两者都不是原子操作。

C语言是汇编层面的实现,后置++的汇编代码比前置++多了一行,那么执行就会多花一点时间。但是随着编译器的不断发展,这样的区别已经微乎其微了。

但是迭代器前置 ++i 与后置 i++ 的效率就有区别了。后置++要多生成一个局部对象 tmp,这个对象有可能包含很多的成员,因此执行速度比前置的慢。在次数很多的循环中,++i和i++可能就会造成运行时间上可观的差别了。

在C++中,由于浮点数的存储方式和精度的问题,直接比较两个float类型的值是否相等可能会出现误差。因此,一般情况下我们不推荐使用"=="或者"!="直接比较两个浮点数是否相等,而是使用以下方法:

使用差值判断:判断两个浮点数之间的差值是否小于一个给定的误差范围,如果小于误差范围则认为两个浮点数相等。

11 怎么避免内存泄漏?了解野指针么?

  1. 动态内存的申请与释放必须配对,防止内存泄漏
  2. 如果返回的是动态分配的内存或对象,必须使用指针,使用引用会产生内存泄漏。
  3. 若存在继承关系时,析构函数必须申明为虚函数,这样父类指针指向子类对象,释放基类指针时才会调用子类的析构函数释放资源,否则内存泄漏

野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)

野指针不同于空指针,空指针是指一个指针的值为null,而野指针的值并不为null,野指针会指向一段实际的内存,只是它指向哪里我们并不知情,或者是它所指向的内存空间已经被释放,所以在实际使用的过程中,我们并不能通过指针判空去识别一个指针是否为野指针。

出现野指针的情况:

  1. 指针变量的值未被初始化: 声明一个指针的时候,没有显示的对其进行初始化,那么该指针所指向的地址空间是乱指一气的。如果指针声明在全局数据区,那么未初始化的指针缺省为空,如果指针声明在栈区,那么该指针会随意指向一个地址空间。
  2. 指针所指向的地址空间已经被free或delete:在堆上malloc或者new出来的地址空间,如果已经free或delete,那么此时堆上的内存已经被释放,但是指向该内存的指针如果没有人为的修改过,那么指针还会继续指向这段堆上已经被释放的内存,这时还通过该指针去访问堆上的内存,就会造成不可预知的结果,给程序带来隐患。
  3. 指针操作超越了作用域

12 c++内存分配了解么?

如上图,从低地址到高地址,一个程序由代码段、数据段、BSS段、堆栈段组成。

  1. 代码段:存放程序执行代码的一块内存区域。只读,不允许修改,代码段的头部还会包含一些只读的常量,如字符串常量字面值(注意:const变量虽然属于常量,但是本质还是变量,不存储于代码段)。
  2. 数据段data:存放程序中已初始化的全局变量和静态变量的一块内存区域。
  3. BSS 段:存放程序中未初始化的全局变量和静态变量的一块内存区域。
  4. 可执行程序在运行时又会多出两个区域:堆区和栈区。**堆区:**动态申请内存用。堆从低地址向高地址增长。栈区:存储局部变量、函数参数值。栈从高地址向低地址增长。是一块连续的空间。
  5. 最后还有一个文件映射区(共享区),位于堆和栈之间。

13 事务的ACID特性?(没记牢,漏了一个)

四个特性

  1. 原子性(Atomicity):原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚。失败回滚的操作事务,将不能对事务有任何影响。
  2. 一致性(Consistency):一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。例如:A和B进行转账操作,A有200块钱,B有300块钱;当A转了100块钱给B之后,他们2个人的总额还是500块钱,不会改变。
  3. 隔离性(Isolation):隔离性是指当多个用户并发访问数据库时,比如同时访问一张表,数据库每一个用户开启的事务,不能被其他事务所做的操作干扰(也就是事务之间的隔离),多个并发事务之间,应当相互隔离。例如同时有T1和T2两个并发事务,从T1角度来看,T2要不在T1执行之前就已经结束,要么在T1执行完成后才开始。将多个事务隔离开,每个事务都不能访问到其他事务操作过程中的状态;就好比上锁操作,只有一个事务做完了,另外一个事务才能执行。
  4. 持久性(Durability):持久性是指事务的操作,一旦提交,对于数据库中数据的改变是永久性的,即使数据库发生故障也不能丢失已提交事务所完成的改变。

14 redis的节点管理?

  1. 集群节点:Redis集群是一种分布式部署方式,它由多个Redis节点组成,每个节点都可以处理读写请求。Redis集群使用哈希槽(hash slot)来分片数据,将数据均匀地分配到不同的节点上。
  2. 主从节点:Redis主从复制是一种数据复制机制,它由一个主节点和多个从节点组成。主节点负责处理读写请求,并将数据同步到从节点上,从节点只负责处理读请求。主从复制可以提高Redis的可用性和可靠性,同时也可以提高读取性能。
  3. 哨兵节点:Redis哨兵是一种自动化的监控和管理机制,它由多个哨兵节点组成,每个哨兵节点都可以监控多个Redis节点的状态。当某个Redis节点出现故障或者下线时,哨兵节点会自动发现并将该节点标记为不可用状态,并选举出新的主节点来代替原来的主节点,从而保证Redis集群的高可用性。

15 kill -9 和kill -15的区别?

正常结束进程的信号,kill -15命令的默认信号。如果进程已经发生了问题,那么这 个信号是无法正常中止进程的,这时我们才会尝试 SIGKILL 信号,也就是信号 9,即强制杀死。

16 僵尸进程怎么产生的?僵尸进程和孤儿进程的区别?哪一个有害?怎么杀死僵尸进程?

  1. 孤儿进程,是指一个父进程退出后,而它的一个或多个子进程还在运行,那么这些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并且由init进程对它们完成状态收集工作。
  2. 僵尸进程,是指一个进程使用fork函数创建子进程,如果子进程退出,而父进程并没有调用wait()或者waitpid()系统调用取得子进程的终止状态,那么子进程的进程描述符仍然保存在系统中,占用系统资源,这种进程称为僵尸进程。

所以两者的区别是:孤儿进程是父进程已退出,子进程未退出;而僵尸进程是父进程未退出,子进程已退出。

  1. 如何解决僵尸进程:(1)一般,为了防止产生僵尸进程,在fork子进程之后我们都要及时使用wait系统调用;同时,当子进程退出的时候,内核都会给父进程一个SIGCHLD信号,所以我们可以建立一个捕获SIGCHLD信号的信号处理函数,在函数体中调用wait(或waitpid),就可以清理退出的子进程以达到防止僵尸进程的目的。(2)使用kill命令。打开终端并输入下面命令:$ ps aux | grep Z会列出进程表中所有僵尸进程的详细内容。然后输入命令:$ kill -s SIGCHLD pid(父进程pid)这样子进程退出后,父进程就会收到信号了。或者可以强制杀死父进程:$ kill -9pid(父进程pid)这样父进程退出后,这些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并且由init进程对它们完成状态收集工作。

以上答案均来自本人专栏:校招面试考点全解析——C++软件与嵌入式篇(蒋豆芽的秋招打怪之旅)

欢迎大家围观:**************************************

#C++#
牛友面经解答 文章被收录于专栏

这个专栏专门用于为牛友解答面经,希望能帮助到大家。

全部评论
这是本科吧?
1 回复 分享
发布于 2023-03-27 15:03 湖北
mark
点赞 回复 分享
发布于 2023-05-18 09:42 北京
本人博客包含C++、机器学习、云计算等一系列面经,有兴趣的同学可以看看我的博客,有专栏可以订阅
点赞 回复 分享
发布于 2023-05-18 09:47 广东
机器学习面试题汇总与解析:https://www.nowcoder.com/creation/manager/columnDetail/qMKkxM
点赞 回复 分享
发布于 2023-06-17 08:29 陕西
云计算面试题全解析 https://www.nowcoder.com/creation/manager/columnDetail/0x97Bm
点赞 回复 分享
发布于 2023-06-17 08:29 陕西
C++与嵌入式面试题全解析:https://www.nowcoder.com/creation/manager/columnDetail/wjvy4m
点赞 回复 分享
发布于 2023-06-17 08:31 陕西

相关推荐

11-05 07:29
贵州大学 Java
点赞 评论 收藏
分享
38 262 评论
分享
牛客网
牛客企业服务