浙江大华 2021 秋招面试总结
岗位:嵌入式软件工程师
浙江大华笔试一共 37 道题,35 道选择填空,2 道编程,时间 60 分钟,C 语言一半,C++ 一半。
一面是晚上九点半打电话过来,过程 15 分钟,可能他们还在加班。
二面是现场面,20 分钟。
现场面流程很快,二面完毕 HR 面,当天面试完毕。一周内发 offer。
一面
1、简单的自我介绍
回答:我主要介绍过去两年我做的项目和个人的知识框架
2、问了一下我主要用的编程语言,我说C
因为他们在做相机类产品的缘故
4、如何防止编译器优化?
回答:volatile
那就顺便解释一下关键词static、const、extern的作用(经典)。
5、在C++代码中嵌入C代码,需要做什么?
回答:extern C
6、进程与线程,分配资源的最小单位是什么?
回答:进程
7、网络编程中长链接和短链接?
回答:
短连接
1、连接->传输数据->关闭连接
2、比如HTTP是无状态的的短链接,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束就中断连接。
3、因为连接后接收了数据就断开了,所以每次数据接受处理不会有联系。 这也是HTTP协议无状态的原因之一。
代码解读
长连接
1、连接->传输数据->保持连接 -> 传输数据-> ...........->直到一方关闭连接,多是客户端关闭连接。
2、长连接指建立SOCKET连接后不管是否使用都保持连接,但安全性较差。
代码解读
什么时候用长连接,短连接?
长连接常用于高频的操作和点对点通信,并且在实际应用中应避免过多地开启链接。建立每个TCP链接都需要执行三步握手流程这意味着在实际应用中应避免过多地开启链接以减少时间消耗。如果每次操作都采用先建立新链接的方式那么整体处理速度将明显下降因此在每次处理完成后无需关闭当前链接下次处理可以直接发送数据包而不必再次建立新链接。例如在数据库应用中通常采用长链接模式而在实际开发中若需频繁使用短链接则可能导致socket异常问题此外在实际应用中频繁创建和关闭socket也会造成资源浪费。
在Web网站中,默认情况下通常采用短链接而非长链接。主要原因在于长连接会对服务器端造成一定的资源消耗。由于Web网站通常面临成千上万甚至上亿数量的同时在线客户端的需求,在这种情况下使用短链接能够显著减少资源消耗。若采用长连接,并且当存在如此庞大的用户基数时(即若每个用户都需要独立占用一个端口),则会导致巨大的压力。因此,在处理大量并发请求的情况下,在不影响用户体验的前提下采用短链接策略更为合适
8、多线程编程中,写线程安全的函数要注意哪些点?
回答:需要注意的地方较多,这与多线程编程的知识有关。需要注意的是所写的函数应当具备可重入特性:当CPU接收特定信号时会暂停当前操作并转向相应的信号处理程序,在该信号处理程序开始执行的过程中可能会再次访问正在执行的任务(即发生重入现象)。为了验证其是否为可重入程序需要确保这些程序完成正常的运行后(即所有被中断的任务都能重新被启动),而这个过程必须保证不会导致死锁或其他异常情况发生。至于其他相关知识,请大家自行查阅资料获取进一步的信息
9、断言(assert)的用法
回答:它不仅仅是一个错误报告工具。实际上,assert 宏的主要功能并非用于错误报告。它主要用于程序调试和异常处理。其原型定义位于include/Assert.h,并且当其条件检测到错误时会触发特定行为
#include "assert.h"
void assert( int expression );
代码解读
assert的作用是用来判断表达式expression的结果是否为假。如果计算结果为false(即等于零),则会首先发送一条错误信息到标准错误日志。接着会调用abort函数来终止整个程序的执行。
用法:
- 在函数入口处验证输入参数的有效性
- 每个断言仅针对单一条件进行验证;当同时对多个条件进行断定时(SEH),难以直接诊断出是哪一个具体条件出现了问题
- 不允许使用可能影响系统状态的操作;由于断言指令仅在调试模式下起作用(SEH),这可能导致程序在正常运行时遇到硬件错误
- 建议将断言指令与其后续代码之间留出至少一个空行以确保良好的可读性和视觉效果
10、内存四区(堆、栈、全局区、代码区)


11、了解几种排序算法,时间复杂度是多少?
十种常见排序算法可以分为两大类:
非线性时间比较类排序:基于比较的方法用于确定元素之间的相对顺序,在算法设计中发现其时间复杂度无法低于O(n\log n)的水平,因此得名非线性时间比较类排序。
线性时间Non-comparison-based排序:无需基于元素间的比较来确定它们的顺序,并能超越基于比较排序的时间下限,在线性时间内完成排序任务

算法优劣评价术语
稳定性:
稳定:如果 a 原本在 b 前面,而 a = b,排序之后 a 仍然在 b 的前面;
不稳定:如果 a 原本在 b 的前面,而 a = b,排序之后 a 可能会出现在 b 的后面;
排序方式:
内排序:所有排序操作都在内存中完成,占用常数内存,不占用额外内存。
外排序:因为数据量庞大,因此必须将大量数据存储在磁盘上。同时,在排序过程中还需要依赖磁盘与内存之间的数据传输来进行运算操作。这种情况下会带来额外的内存空间需求。
复杂度:
时间复杂度: 一个算法执行所耗费的时间。
空间复杂度: 运行完一个程序所需内存的大小。


至于各种算法的原理及其实现细节, 因为种类繁多且内容较为深入, 在本文中不做详细阐述. 但建议了解两本经典的教材: 《啊哈! 算法》、《大话数据结构》.
存在大量不同的排序算法可供选择,在嵌入式系统中所需掌握的基本方法相对较少。基础方法如冒泡排序、快速排序和插入排序能够有效解决许多实际问题。较为复杂的场景通常涉及动态规划方法或图论中的路径问题,在嵌入式系统领域中涉及这些高级内容的可能性较低。只有软件开发相关的岗位才需要掌握这类知识。需要注意的是大公司和独角兽公司的招聘要求会相应提高难度系数
二面
二面是现场面试,大概 20 分钟左右。
1、对着简历面试,问你简历写的东西。
针对你的笔试题目,请观察你在题目的解答情况。随机选择一个题目,请你详细说明正确答案或错误答案的原因。(因此,在笔试结束后必须彻底理解每一个答案)。
针对你的笔试题目,请观察你在题目的解答情况。随机选择一个题目,请你详细说明正确答案或错误答案的原因。(因此,在笔试结束后必须彻底理解每一个答案)。
3、问进程线程,经典问题。
4、问 strcpy拷贝函数安全吗,如果不安全,用什么去替代。
字符串复制函数存在安全隐患,在使用过程中可能会导致系统资源占用异常增加,并最终引发内存溢出问题;主要原因是该函数缺乏必要的检查机制,在未对数据长度进行校验的同时也未能验证目标存储区域的有效性
char *strcpy(char *strDest,const char *strSrc)
代码解读
然而进行了计算,在c_strncpy.h中描述的COPY函数虽然存在安全隐患,并未对目标区域进行边界校验。
strncpy(dest, src, sizeof(dest));
代码解读
strncpy_s是安全的
该函数用于数据拷贝。相比而言,它与字符串复制函数的主要区别在于该函数支持任意数据类型的复制,并非仅限于字符串类型。
memcpy函数负责将源内存(由src指针所指向的内存块)复制到目标记忆空间(由dest指针所指向的位置)。其中有一个称为size变量的参数决定了复制的数据量。
void *memcpy(void *dest, void *src, unsigned int count);
代码解读
5、写一个双向链表的插入删除
6、解释一下动态内存和静态内存
- 静态内存的分布会在编译阶段完成,并不会消耗CPU资源;而动态内存的申请和回收则发生在程序运行阶段,并会消耗CPU资源。
- 静态内存量处于堆栈顶端位置;而动态内存量位于堆区中。
- 动态内存量的实现依赖于指针和引用的支持功能;而静态内存量不需要这些功能。
- 静态内存的管理是预先规划好的任务由编译器完成;而动态内存的申请和回收则由程序员来处理。
