分享快手客户端面经(已OC)
可能有的内容答得不完善不正确,请大家注意甄别。
一面(9.19 50min)
1. 自我介绍、项目
2. OC 生命周期(ViewController 生命周期,各阶段需要处理的操作),内存管理策略(MRC,ARC,自动释放池)
3. C++ 内存管理策略(程序员手动管理内存的申请和释放,使用智能指针管理堆中对象的生命周期)
4. C++ 动态和静态是什么?(编译和运行时:动态/静态多态,动态/静态绑定,动态/静态数组等)
5. 纯虚函数的调用过程是?(虚函数表)
6. 设计模式:了解哪些设计模式?设计模式的由来是什么(答:过去开发人员的经验总结)
7. C 和 C++ 的区别(面向对象特性等)
8. 引用 调用拷贝构造函数了吗(不使用,只有3种情况会使用拷贝构造函数:1.用 A a2(&a1) 或 A a2 = a1 的方式显式调用;2.使用值作为函数参数传递;3.使用值作为函数返回值传递(不一定,vs 会调用,g++ 不调用)
9. OC 的 UI(不了解)
10. OC protocol(类似 Java 中的接口,包括一组需要实现的函数声明,其中有必须(@required)实现和选择实现的(@optional),可以帮助实现类似C++中的多继承)
11. HTTP 和 HTTPS 区别(密文传输,多一层安全套接字层,需要多做一组TLS握手,HTTPS建立到第一次发信的过程,基于离散对数(DH)的和基于大数质因子分解(RSA)的在是线上的区别)
12. 可以使用私钥加密吗,什么时候使用(对消息的验证性和不可否认性)
13. 哈希值特点(大部分哈希运算都是从大容量信息计算小容量文本,所以不可逆;对源信息的简单修改都会极大程度地改变哈希值,方便用于消息完整性确认)
14. 信息摘要算法(用于消息完整性确认的,HTTPS 锁组件(TLS_密钥交换和证书验证_WITH_对称加密_摘要)中的最后一个算法,MD 家族,SHA 家族)
15. 怎么安全的保存密码(密码不可以明文存,因为攻击服务器比攻击加密通信容易得多,可以存哈希值,保证用户密码对服务器不可见)
16. 如果密码比较简短,如何保证安全(密码过于简短,能够生成的哈希值数目也有限,容易被查表攻击或彩虹表攻击,可以用合理加盐的方法解决,增加对整个库攻击的时间/空间复杂度(升级为盐位和密码位笛卡尔积))
17. 如果黑客截获了我的报文,重新向服务器发送,如何防范(可以用时间戳解决)
18. 平时用什么网站去查不会的问题
19. 算法:二叉树层次遍历
二面(9.23 1h10min)
1. C++ 从代码到可执行文件的过程(预处理:将宏定义展开替换到代码中的指定位置,删除注释内容等;编译:词法和语法分析,代码优化;汇编:生成机器码;链接:链接某些静态/动态库,打包成可执行文件)
2. 可执行文件的结构(C++程序的内存模型栈区,文件映射区,堆区,全局区(data(已初始化),bss(未初始化),rodata(常量)),代码区)
3. 静态链接和动态链接(发生时期不同,动态链接具有更好地代码复用性,但是跨平台通用性差一些,能瘦身可执行文件,静态链接相反;动态库 XXX.a,静态库 XXX.lib)
4. 堆和栈(栈由编译器管理,内存地址自上向下生长,无内存碎片,不需要程序员手动释放,空间较小;堆由程序员手动管理或智能指针辅助管理,内存地址自下向上生长,可能有先申请但已释放,但后申请的未释放造成的内存碎片,ptmalloc 用一个哈希表帮助管理这些内存碎片(合并,分配),空间较大。堆在发生 malloc 的时候会根据申请的大小使用 brk() 或 mmap() 系统调用,这是实际从用户态陷入内核态向操作系统申请内存空间的操作。malloc() 的大小未必等于 brk() 的大小,brk() 会申请出一个内存池,由 ptmalloc 管理;当堆的上方申请空间(top chunk)足够大会发生 brk 紧缩,这是实际从用户态陷入内核态向操作系统归还内存空间的操作)
5. 段页管理(操作早期使用的段式管理可能造成外部碎片(空闲内存大于需要装入的程序的所需空间,但无法装入);用页式管理可以避免外部碎片的产生,操作系统为每个进程分配 4G(32位)的虚拟地址空间,当访问某一地址空间,通过查页表(多级页表,快表等)找到实际的物理地址)
6. 缺页中断(缺页中断是一种故障(fault),当首次读写 touch 到未映射在内存(minor fault 建立内存映射即可,major fault 需要把内容从磁盘 swap 出来再建立映射)的时候,会从用户态陷入内核态,用缺页中断处理函数建立映射,然后在从内核态回到用户态,继续执行当前的这条代码)
7. 死锁产生和解决方法(资源互斥,占有并保持,不释放,循环等待4个必要条件,解决方法可以用银行家算法决策是否分配资源,已发生死锁后可以杀死(mysql发生死锁回滚某一事务)其中某一进程释放资源)
8. 项目
9. 算法:二叉树z字型遍历
三面(9.29 35min)
1. 自我介绍
2. 为什么选择客户端开发
3. 客户端和个人项目之间的区别
4. 项目中的性能优化(用多线程利用处理器多核性能,用缓存处理多个处理的速度差异,用预处理减少需要处理的无用信息总量,延迟加载减少对能耗和内存的负担)
5. 为什么加锁相比信号量处理同步会比较麻烦(锁更多地用于处理资源互斥,但是也可以用于做线程同步,相比用于处理线程同步的信号量语义实现上会比较复杂)
6. 粘包(使用裸 TCP 进行通信或应用层协议开发者对 TCP 字节流传输的理解不到位导致的,某些来自不同应用程序的数据使用同一 TCP 连接,被放在了同一个 TCP 包中在接收端无法被正确区分导致的,可以用固定长度(不灵活)、某些标识(telnet的/r/n)、设计应用层包结构(HTTP头部))
7. HTTP不同版本区别(1.1:长连接与管道传输;2:并发传输(多个 stream 复用一个 TCP 连接,为解决队头阻塞做出的努力)、二进制传输(不光支持 ASCII 码内容传输,对消息类型适用性好)、头部压缩(静态表,动态表用索引值代替字段,哈夫曼压缩字段中的内容)、服务器主动推送;3:改 TCP-based 为 UDP-based(QUIC)(完全解决队头阻塞),用连接号标识连接(解决TCP用四元组标识通信在网络切换时发生的开销))
8. UDP怎么处理丢包(对消息在应用层加序列号,在应用层检查是否有丢包发生,把丢失信息返回给发送端?)
9. 项目中遇到的设计模式,适配器模式和代理模式的区别(适配器模式的动机是两个接口本身不适配,需要一个适配器类来适配这两个类;代理模式的动机是不想跟委托类发生交互,所以用一个代理类解决其他类与委托类发生的交互操作?)
10. 算法:连续最长有效括号
HR面(10.10 25min)当晚已OC
#我拿到offer啦#