安恒信息 C++开发 一面
1. 自我介绍
2. 既然你在项目中管理了大量内存,讲讲 std::unique_ptr 自定义删除器(Deleter)的用法和场景?
解答: 智能指针不仅可以管理内存,还能管理文件描述符(fd)、Socket连接或各种硬件资源。为了防止资源泄漏,可以给 unique_ptr 传入自定义删除器。相比于 shared_ptr 在运行时通过类型擦除调用删除器,unique_ptr 的删除器类型是模板参数的一部分,在编译期绑定,几乎没有额外开销。
#include <memory>
#include <unistd.h>
struct FdDeleter {
void operator()(int* fd) const {
if (fd && *fd >= 0) {
close(*fd);
delete fd;
}
}
};
// 使用:
std::unique_ptr<int, FdDeleter> safe_fd(new int(socket(...)));
3.计算机网络中,如果对端机器处理极慢,导致 TCP 接收窗口降为 0,会发生什么?如何恢复?
这就是 TCP 零窗口(Zero Window) 问题。当服务端的应用层(如你的消费者进程)由于阻塞未调用 read,导致系统接收缓冲区满时,会向客户端发送 Window=0 的 ACK 包。此时客户端的发送方会停止发送数据。为了避免死锁(即服务端后来有了窗口,但更新窗口的包丢了),客户端会启动一个零窗口探测定时器(Zero Window Probe),周期性地发送只包含 1 字节数据的探测包,强制服务端响应当前的真实窗口大小,直到窗口恢复后继续发送。
4. 介绍一下你简历上这两个项目中觉得更有挑战的一个?
5. 项目中网络通信没自己写,而是用的 muduo 库?那你介绍一下你在其他项目实现的 epoll 服务器?
我实现的 epoll 服务器是一个典型的 Reactor 模型(One Loop Per Thread)。
- 主线程运行 main Reactor,只负责监听监听套接字(listenfd),当有新连接进入时,触发 epoll_in 事件,调用 accept 获取新连接。
- 然后通过轮询或 Hash 算法,将这个新连接的 fd 分发给后端的 Thread Pool 中的某个 sub Reactor。
- sub Reactor 将该 fd 注册到自己的 epoll 实例中,专门负责处理这个连接后续的读写、数据解析和业务逻辑。
6. 你的 epoll 服务器没有使用第三方库进行序列化?那你介绍一下自定义的通信协议?
由于没有使用 Protobuf,我采用的是 TLV (Type-Length-Value) 格式的二进制自定义协议,这样能有效解决 TCP 粘包和半包问题。在 Socket 接收端,我会设定一个固定大小的 Header(比如 4 字节的 Package Length + 2 字节的 MSG_TYPE)。每次 read 时,先读满 Header 长度以解析出 Body 的大小;然后继续在缓冲区中等待,直到接收到的字节数等于 Body Length,才认为拼接出了一个完整的数据包,进而反序列化并抛给业务层。
7. 你的网络库是对 muduo 进行了二次封装?为什么把 connect 封装成 channel?
是的。在 muduo 的设计哲学中,Channel 是对文件描述符(fd)及其关心的 epoll 事件(如 EPOLLIN, EPOLLOUT)的直接封装。将由 connect 建立的 socket fd 封装为 channel 的好处是:彻底分离了底层 IO 事件与上层业务逻辑。Channel 内部保存了各种事件的回调函数(读、写、错误、关闭)。当 epoll 返回活跃事件时,直接根据触发的 Channel 执行其预设的回调,满足了高内聚、低耦合的非阻塞异步编程需求。
8. 再说一下日志系统,你采用的是双缓冲设计是吧,具体怎么设计的?
双缓冲(Double Buffering)主要是为了避免前端业务线程的打日志操作被磁盘 IO 阻塞。
- 准备两个 Buffer(A 和 B)。前端工作线程将日志追加到内存 Buffer A 中(只需加轻量级自旋锁或无锁队列,极快)。
- 后台专门有一个落盘线程。当 Buffer A 写满或到达定时器的刷新时间时,前后台快速交换(Swap) Buffer A 和 Buffer B 的指针。
- 交换后,前端继续将新日志写到 Buff
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
本专栏系统梳理C++方向, 大中厂高频高频面试考点 , 内容皆来自真实面试经历,从基础语法、内存管理、STL与设计模式,到操作系统与项目实战,结合真实面试题深度解析,帮助开发者高效查漏补缺,提升技术理解与面试通过率,打造扎实的C++工程能力.
查看8道真题和解析