【23年9月】上海戎磐网络科技实习生一面
十多分钟就面完了,堪称急速,面试官说我答的不错;而且上来自我介绍完毕后就问问题,不多比比🤣
注意:这是23年的老面经!
知识点
1.Linux下线程互斥怎么实现
加锁,pthread,然后我还提到了cpp的原子变量
2.CPP多态怎么实现
虚函数表,巴拉巴拉
3.CPP为啥要引入模板
代码更高复用
4.NAT怎么实现的?
转化表,IP地址替换,巴拉巴拉吧说一大堆
5.进程通信
老问题了
6.inet_ntoa函数知道吗?连续调用会有什么问题?
这是最后一个问题,面试官说我答的挺好的
我先说了这个函数是用于16位IP地址和字符串的转换的;
然后面试官这里问了一个业务上的问题,口述的
printf("%s %s\n",inet_ntoa(x),inet_ntoa(y));// x和y是两个ip地址
这个函数会不会有什么错误的地方?
请注意,这里是面试时候的描述,面试官肯定只能给你描述个大概的,并不会细致到具体的传参应该传什么类型的变量,所以传参x和y也只是个伪代码,想问的地方不在这里!
这里我说了inet_ntoa
是采用static变量来返回ip字符串的,线程不安全,有可能两个调用最终返回了一个相同的IP地址,又明说了我不确定;(这样调用肯定有问题,不然问你干嘛?)
面试结束了,来测试一下到底是啥情况吧!
#include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> int main() { struct in_addr ip1; struct in_addr ip2; inet_aton("192.168.3.1",&ip1); inet_aton("10.161.33.42",&ip2); printf("%s %s\n",inet_ntoa(ip1),inet_ntoa(ip2)); return 0; }
运行结果如下,两个IP地址返回了同一个,我猜对了;
$ ./test 192.168.3.1 192.168.3.1
为什么呢?打印一下地址,会得到如下输出,两次调用返回了相同的地址,自然打印出来的结果相同;
printf("%x %x\n",inet_ntoa(ip1),inet_ntoa(ip2)); // 输出 68db1ef0 68db1ef0
对于这个函数而言,它需要给我们返回一个字符串,又必须保证这个字符串能在函数外被正常访问(不能被释放),再加上这是一个C语言接口,那么就只有三种方案了
- 函数里面malloc,需要用户手动free
- static变量
- 让用户传入一个有效的地址,将数据写入作为输出型参数
第一个方案肯定是不可行的!这相当于官方提供了一个极其容易导致内存泄漏的接口!这不得被开发者喷死?比如本题提到的场景里面就是两次printf而已,除此之外没有保存这个返回值,更别提free了,这里就直接两次内存泄漏了!
printf("%s %s\n",inet_ntoa(ip1),inet_ntoa(ip2)); // 如果用malloc后的字符串地址做返回值,这里就是两个内存泄漏
第三个方案也不方便,系统依赖用户传入一个数组的入参,我们知道ipv4的IP地址字符串最长是3*4+3=15
位,那么如果用户只传入一个char arr[12]
呢?越界访问的问题怎么解决?相当于系统之中依旧会出现参数不匹配而可能导致的地址访问错误!
而这个函数本身的工作很简单,完全没必要弄那么复杂;
最终linux系统采用了static变量的方式,来返回这个IP地址的字符串;man手册里面是这么说的,直接看最后一句,翻译过来的意思是后续的调用会覆盖掉前面的值;
The inet_ntoa() function converts the Internet host address in, given in network byte order, to a string in IPv4 dotted-decimal notation. The string is returned in a statically allocated buffer, which subsequent calls will overwrite.
所以最终我们看到的结果就是两次打印出了相同的IP地址;
这里还涉及到第二个知识点,printf的传参顺序;
简单说来就是printf是从右往左执行的(其实所有函数的传参都是这样,这也是为什么缺省值要从右边往左给)
printf("%s %s\n",inet_ntoa(ip1),inet_ntoa(ip2));
这里的执行顺序如下
- ip2结构体传给函数,转成ip地址字符串后存在static变量中
- ip1结构体传给函数,转成ip地址字符串后存在了static变量中,覆盖了ip2的结果
最终打印出来的两个字符串都是ip1的地址!
对于inet_aton
函数而言,正确的调用办法是每次调用后都取走返回的IP地址字符串,可以用std::string
接收,也可以用strcmp拷贝到一个自己定义的字符串数组变量中,反正得想办法接受了第一个的结果再去调用第二次。
项目
当时写的是个比较基础的视频播放项目,实现的比较简陋,这些高级功能一个都没实现。
1.视频点播传一半关闭了怎么解决
两次面试都问到了这个问题,我提到了将新的文件和本地已有文件进行校验,跳过已有数据
2.传一半剩下的数据后端怎么处理,什么时候删除?
我提到了前后端用md5验证来确认视频文件无误,如果有问题,可以设置一个定时器,一小时后删除错误的数据
3.用户修改了视频后上传怎么处理?
同第一个,进行一定的数据校验,然后再复写没有的数据;
效率!
面经还没写完,结果已经出啦,过了初试!但是要线下复试。
#暑期实习#笨蛋CPP选手记录的面经。