【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选手记录的面经。

全部评论

相关推荐

点赞 1 评论
分享
牛客网
牛客企业服务