更多课程 选择中心

C/C++培训
达内IT学院

400-996-5531

C/C++后台开发面试难不难,京东二面

  • 发布:C++培训
  • 来源:C++职场
  • 时间:2020-06-15 17:07

很多人因为找C/C++工作,会在网上收集了很多C语言方面的面试题以及答案。今天,我决定把一些关于c的资料发出来,送给有需要的朋友,免得到处搜寻,实在辛苦。上一篇已经为大家讲解过一面了,今天主要说一说京东面试当中的二面,内容属实有点多,整理不易。

发布之前先申明两点:

1、所有资料来自网络,本人只是收集和转发。

2、所有问题解答(尤其是代码)只是参考,不保证正确。

面试官:你觉得你的一面感觉如何

我:我说一面面试官很好(其实我从之前的沟通中已经感觉一面二面是同一个面试官了),不太会的都会引导我,然后回头查了相关的资料。面试官还是比较满意的。注意:复盘很重要,一般都有面试记录的。

我看你写了三个项目,说一个熟悉一些的,背景,你做了啥,有什么难点

    面试官:我们看几个简单题

构造函数为什么不能是虚函数虚函数的调用需要虚函数表指针,而该指针存放在对象的内容空间中;若构造函数声明为虚函数,那么由于对象还未创建,还没有内存空间,更没有虚函数表地址用来调用虚函数。

原子变量和volatile区别(C++11)Volatile变量可以确保先行关系,即写操作会发生在后续的读操作之前, 但它并不能保证原子性。例如用volatile修饰count变量那么 count++ 操作就不是原子性的。而AtomicInteger类提供的atomic方法可以让这种操作具有原子性如getAndIncrement()方法会原子性的进行增量操作把当前值加一,其它数据类型和引用变量也可以进行相似操作。

智能指针介绍(C++11)1.auto_ptr主要是用来解决资源自动释放的问题;auto_ptr支持赋值和复制,将指针的所有权转移,但是如果转移后再访问原来得指针,行为不确定,程序可能会在运行时出错。

2.unique_ptr与auto_ptr一样,也是建立所有权机制,但是不支持复制和赋值,所以将一个unique_ptr对象赋值给另一个时,程序编译出错;但如果将临时的unique_ptr赋值或复制给另一个对象时,没有问题。unique_ptr比auto_ptr更安全。

3.shared_ptr和unique_ptr都只能一个智能指针引用对象,而shared_ptr则是可以多个智能指针同时拥有一个对象。shared_ptr实现方式就是使用引用计数。引用计数的原理是,多个智能指针同时引用一个对象,每当引用一次,引用计数加一,每当智能指针销毁了,引用计数就减一,当引用计数减少到0的时候就释放引用的对象。这种引用计数的增减发生在智能指针的构造函数,复制构造函数,赋值操作符,析构函数中。

这种方式使得多个智能指针同时对所引用的对象有拥有权,同时在引用计数减到0之后也会自动释放内存,也实现了auto_ptr和unique_ptr的资源释放的功能。

4.weak_ptr,shared_ptr是一种强引用的关系,智能指针直接引用对象。那么这个会代码一个隐含的问题,就是循环引用,从而造成内存泄漏,首先来看一个循环引用的例子。

class Parent

{

public:

shared_ptr<Child> child;

};

class Child

{

public:

shared_ptr<Parent> parent;

};

void Function()

{

shared_ptr<Parent> pA(new Parent);

shared_ptr<Child> pB(new Child);

pA->child = pB;

pB->parent = pA;

}

//第一条语句使得pA引用了Parent一个指针,Parent引用计数为1

//第二条语句使得pB引用了Child一个指针,Child引用计数为1

//第三条语句,调用了shared_ptr<Child>类的赋值操作符,使得Child引用计数变为2

//第四条语句,调用了shared_ptr<Parent>类的赋值操作符,使得Parent引用计数变为

//函数返回之前调用了shared_ptr<Parent>和shared_ptr<Child>类的析够函数,使得Child引用计数变为1,Parent引用计数变为1

咱们看,函数执行完之后new出来的Parent和Child并没有释放,所以出现了内存泄漏(说出这几个字之前,自己应该至少知道哪些工具可以检测内存泄漏等相关问题)。

出现泄漏的原因就是pA和pB相互引用了,导致两者所引用对象的引用计数不能减少到0,造成泄漏。

如果把第三条语句或者第四条语句任意删除一个,就不会有泄漏了。这就是强引用所带来的问题。weak_ptr从字面意思上可以看出是一个弱指针,不是说明这个指针的能力比较弱,而是说他对他所引用的对象的所有权比较弱,说得更直接一点儿就是他并不拥有所引用对象的所有权,而且他还不能直接使用他所引用的对象。

在stl中,weak_ptr是和shared_ptr配合使用的,在实现shared_ptr的时候也就考虑了weak_ptr的因素。weak_ptr是shared_ptr的观察者,它不会干扰shared_ptr所共享对象的所有权,当一个weak_ptr所观察的shared_ptr要释放它的资源时,它会把相关的weak_ptr的指针设置为空,防止weak_ptr持有悬空的指针。注意:weak_ptr并不拥有资源的所有权,所以不能直接使用资源。可以从一个weak_ptr构造一个shared_ptr以取得共享资源的所有权。

weak_ptr是为配合shared_ptr而引入的一种智能指针,它更像是shared_ptr的一个助手,而不是智能指针,因为它不具有普通指针的行为,没有重载operator*和operator->,它的最大作用在于协助shared_ptr,像旁观者那样观测资源的使用情况。

weak_ptr被设计为与shared_ptr共同工作,可以从一个shared_ptr或者另一个weak_ptr对象构造,获得资源的观测权。但weak_ptr没有共享资源,它的构造不会引起指针引用计数的增加。同样,在weak_ptr析构时也不会导致引用计数的减少,它只是一个静静地观察者。

使用weak_ptr的成员函数use_count()可以观测资源的引用计数,另一个成员函数expired()的功能等价于use_count() == 0,但更快,表示观测的资源(也就是shared_ptr管理的资源)已经不复存在了。

weak_ptr 没有重载operator*和->,这是特意的,因为它不共享指针,不能操作资源,这是它弱的原因。但它可以使用一个非常重要的成员函数lock()从被观测的shared_ptr获得一个可用的shared_ptr对象,从而操作资源。当expired() == true的时候,lock()函数将返回一个存储空指针的shared_ptr。

智能指针内部实现(C++11)智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象共享同一指针。每次创建类的新对象时,初始化指针并将引用计数置为1;

当对象作为另一对象的副本而创建时,拷贝构造函数拷贝指针并增加与之相应的引用计数;对一个对象进行赋值时,赋值操作符减少左操作数所指对象的引用计数(如果引用计数为减至0,则删除对象),并增加右操作数所指对象的引用计数;

调用析构函数时,构造函数减少引用计数(如果引用计数减至0,则删除基础对象)。智能指针就是模拟指针动作的类。所有的智能指针都会重载 -> 和 * 操作符。智能指针还有许多其他功能,比较有用的是自动销毁。这主要是利用栈对象的有限作用域以及临时对象(有限作用域实现)析构函数释放内存。

DPDK内部实现(这个是因为简历上有写,关于一个高性能数据包处理库)Winpcap:它的一个流程是npf网络组包过滤器首先负责从网络中采集数据包,完成数据的过滤拷贝到内核缓存区,然后调用相应的动态库文件将数据传递到应用层缓冲区,最后应用程序处理。具体工作原理

(1)网卡接受数据包到达信息,然后产生硬件中断,通知cpu调度处理,中断服务程序判断数据包的有效性,分配一个缓冲。

(2)BPF模块根据用户的规则过滤数据包,并把数据包插入到内核的网卡驱动缓冲队列中。

(3)用户程序通过系统调用用来读取内核缓冲区的数据包 完成数据采集。

优化方案:

(1)使用双缓冲减少线程锁。

(2)多线程。

(3)将原始的数据包还原成流保存 减少对数据包的存储,在内核层提供了通用socket环形缓冲,不进入内核协议栈,最后在应用层通过socket链接同时使用mmap技术直接访问socket环状缓冲区

libevent结构、内部实现(回调+同步)、多线程实现首先I/O复用经过封装;

统一事件源(I/O事件,信号事件,定时事件);

事件处理提前注册(回调函数)。

Libevent是线程不安全的,但是libevent提供了锁机制,而且在实现框架上尽量避免使用锁,像memcache多线程使用libevent,他的实现现架是主线程监听到读写事件分发任务(使用CQ队列),每个工作线程对应一个CQ队列。

上面提到的两个网络库可以去看看,资料很全的。

epoll内部实现红黑树 就绪事件双向链表;每当就绪事件到来时,通过实现注册好的回调函数将就绪事件加入到就绪事件队列中,epoll_wait返回时只需要遍历就绪事件双向链表。

timewait作用客户端收到服务的释放连接的请求后,不是立马进入CLOSE状态,而是还要再等待2MSL。理由是:

确保最后一个确认报文能够到达。如果没能到达,服务端就会会重发FIN请求释放连接。等待一段时间没有收到重发就说明服务的已经CLOSE了。如果有重发,则客户端再发送一次LAST ack信号

等待一段时间是为了让本连接持续时间内所产生的所有报文都从网络中消失,使得下一个新的连接不会出现旧的连接请求报文。

版权声明:转载文章来自公开网络,版权归作者本人所有,推送文章除非无法确认,我们都会注明作者和来源。如果出处有误或侵犯到原作者权益,请与我们联系删除或授权事宜。

预约申请免费试听课

填写下面表单即可预约申请免费试听!怕钱不够?可就业挣钱后再付学费! 怕学不会?助教全程陪读,随时解惑!担心就业?一地学习,可全国推荐就业!

上一篇:C/C++后台开发面试难不难,来看看京东
下一篇:不得不知道的八个C语言面试题

几个C语言经典基础算法(含代码)

不得不知道的八个C语言面试题

C/C++后台开发面试难不难,京东二面

C/C++后台开发面试难不难,来看看京东

Copyright © 2023 Tedu.cn All Rights Reserved 京ICP备08000853号-56 京公网安备 11010802029508号 达内时代科技集团有限公司 版权所有

选择城市和中心
黑龙江省

吉林省

河北省

湖南省

贵州省

云南省

广西省

海南省