面试经验|Visual C++:红鸟网络(C++平台工程师)

  1. 内存泄漏的原因及解决办法

内存泄漏是什么?(补充:内存泄漏与内存溢出的区别)

内存泄漏:程序没有释放不在使用的内存,该内存不能被再次使用。这里的内存通常指堆内存,应用程序使用malloc,realloc,new等函数从堆中分配一个内存,当不在使用这些内存时必须对该内存进行释放(使用free或delete函数),否则就会出现内存泄漏。

内存泄漏常见情形:

http://blog.csdn.net/haimianjie2012/article/details/56496047

内存溢出:运行程序要求的内存超出系统所能分配的范围。当程序或游戏运行时所需要的内存超出你主机安装内存所能承受的范围时,程序或游戏运行不了,系统会报内存溢出错误,有时候会自动关闭软件,重启电脑或程序释放部分资源后,又可以正常运行。

参考文献:

http://www.th7.cn/Program/cp/201501/365748.shtml

参考文献:

https://my.oschina.net/u/586637/blog/217710

2.C++虚函数的作用及其实现方式?纯虚函数的作用?

3.引用和指针有什么区别?

指针指向一个内存,它的内容是所指内存的地址;引用是某块内存的别名;

作为函数参数时,都是地址传递,会改变参数的值。

引用定义的是必须初始化,而且初始化之后不能修改,引用自始至终只指向一个地址;指针定义时可以不用初始化,可以指向多个地址,所以可能造成内存泄漏;引用更加安全;

引用不能定义为空,指针可以为空指针。

Sizeof(引用)结果为变量所占内存大小;sizeof(指针)==4,为地址值的大小。

++运算,指针指向下一个内存地址,引用为变量值加1

引用为变量别名,可以像使用变量一样使用引用,而指针在使用时需要*操作符;

4.TCP和UDP的差别?什么是IOCP?网络编程TCP包一般定义为多大?

http://c.biancheng.net/cpp/html/3047.html

http://blog.csdn.net/neicole/article/details/7549497/

(TCP)传输控制协议,是一种提供可靠数据传输的通用协议。

(UDP)用户数据报协议,是一个面向无连接的协议。采用该协议不需要两个应用程序先建立连接。UDP协议不提供差错恢复,不能提供数据重传,因此该协议传输数据安全性差。

3、TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的

UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)

4、每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信

5、TCP首部开销20字节;UDP的首部开销小,只有8个字节

6、TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道

TCP一般用于文件传输(FTP HTTP 对数据准确性要求高,速度可以相对慢),发送或接收邮件(POP IMAP SMTP 对数据准确性要求高,非紧急应用),远程登录(TELNET SSH 对数据准确性有一定要求,有连接的概念)等等;UDP一般用于即时通信(QQ聊天 对数据准确性和丢包要求比较低,但速度必须快),在线视频(RTSP 速度一定要快,保证视频连续,但是偶尔花了一个图像帧,人们还是能接受的),网络语音电话(VoIP 语音数据包一般比较小,需要高速发送,偶尔断音或串音也没有问题)等等。

5.请说出死锁的原因,死锁的四个必要条件,死锁的处理?

一. 什么是死锁?

     如果一个进程集合里面的每个进程都在等待这个集合中的其他一个进程(包括自身)才能继续往下执行,若无外力他们将无法推进,这种情况就是死锁,处于死锁状态的进程称为死锁进程

二. 死锁产生的原因?

1.因竞争资源发生死锁 现象:系统中供多个进程共享的资源的数目不足以满足全部进程的需要时,就会引起对诸资源的竞争而发生死锁现象

(1)可剥夺资源和不可剥夺资源:可剥夺资源是指某进程在获得该类资源时,该资源同样可以被其他进程或系统剥夺,不可剥夺资源是指当系统把该类资源分配给某个进程时,不能强制收回,只能在该进程使用完成后自动释放 

(2)竞争不可剥夺资源:系统中不可剥夺资源的数目不足以满足诸进程运行的要求,则发生在运行进程中,不同的进程因争夺这些资源陷入僵局。

举例说明:  资源A,B; 进程C,D

资源A,B都是不可剥夺资源:一个进程申请了之后,不能强制收回,只能进程结束之后自动释放。内存就是可剥夺资源

进程C申请了资源A,进程D申请了资源B。

接下来C的操作用到资源B,D的资源用到资源A。但是C,D都得不到接下来的资源,那么就引发了死锁。

(3)竞争临时资源

2.进程推进顺序不当发生死锁

三. 产生死锁的四个必要条件?

(1)互斥条件:进程对所分配到的资源不允许其他进程进行访问,若其他进程访问该资源,只能等待,直至占有该资源的进程使用完成后释放该资源

(2)请求和保持条件:进程获得一定的资源之后,又对其他资源发出请求,但是该资源可能被其他进程占有,此事请求阻塞,但又对自己获得的资源保持不放

(3)不可剥夺条件:是指进程已获得的资源,在未完成使用之前,不可被剥夺,只能在使用完后自己释放

(4)环路等待条件:是指进程发生死锁后,必然存在一个进程--资源之间的环形链

四. 处理死锁的基本方法

1、采用资源静态分配策略,破坏"部分分配"条件;

2、允许进程剥夺使用其他进程占有的资源,从而破坏"不可剥夺"条件;

3、采用资源有序分配法,破坏"环路"条件。

死锁的避免不严格地限制死锁的必要条件的存在,而是系统在系统运行过程中小心地避免死锁的最终发生。最著名的死锁避免算法是银行家算法。死锁避免算法需要很大的系统开销。

解决死锁的另一条途径是死锁检测方法,这种方法对资源的分配不加限制,即允许死锁的发生。但系统定时地运行一个"死锁检测"程序,判断系统是否已发生死锁,若检测到死锁发生则设法加以解除。

解除死锁常常采用下面两种方法:1、资源剥夺法;2、撤消进程法

6.写出程序的运行结果

7.存储过程是什么,有什么作用

存储过程(stored procedure)是一组为了完成特定功能的sql 语句集,经编译后存储在数据库。用户通过指定存储过程的名字并给出参数来执行它。

优点:

1.允许标准组件式编程,存储过程被创建后可以被程序多次调用,而不需要重新编写存储过程的sql语句;随时都可以修改存储过程,而且修改存储过程之后,不会对应用程序产生影响,因此具有很好的移植性。

2.存储过程能够实现较快的执行速度,如果某一操作包含大量transaction-sql或者会被多次执行,那么存储过程的速度会比批处理快很多。因为,存储过程是预编译的,在首次运行一个存储过程时,查询优化器对sql语句进行分析、优化后存储在系统表的执行计划中。但批处理每次都需要编译和优化。

3.降低网络流量:调用存储过程不需要传送大量的sql语句,只需要传送调用语句,因此大大减少了网络流量和网路负载;

4.系统管理员可以设置存储过程的访问权限,从而保证数据的安全性。

8.熟悉STL吗,STL容器,list、vector、map的区别是什么?

,C++标准程序库 和C++stl是比较好的入门且使用的书籍,以后有了一定的STL经验,再去研究《STL源码剖析》和《Effective STL》

http://www.cnblogs.com/raichen/p/5817158.html

http://www.cnblogs.com/biyeymyhjob/archive/2012/07/22/2603525.html

STL(Standard Template Library),即标准模板库,包含了诸多在计算机科学领域里所常用的基本数据结构和基本算法。STL提供六大组件,彼此可以组合套用:

1.容器

容器就是各种数据结构,我就不多说,看看下面这张图回忆一下就好了,从实现角度看,STL容器是一种class template。

2.算法

各种常见算法,如sort,search,copy,erase等,从实现角度看,STL算法是一种function template。用来操作容器中的数据,函数本身与他们操作的数据的结构和类型无关。

1。vector  (连续的空间存储,可以使用[]操作符)快速的访问随机的元素,快速的在末尾插入元素,但是在序列中间岁间的插入,删除元素要慢,而且如果一开始分配的空间不够的话,有一个重新分配更大空间,然后拷贝的性能开销.

2。deque (小片的连续,小片间用链表相连,实际上内部有一个map的指针,因为知道类型,所以还是可以使用[],只是速度没有vector快)快速的访问随机的元素,快速的在开始和末尾插入元素,随机的插入,删除元素要慢,空间的重新分配要比vector快,重新分配空间后,原有的元素不需要拷贝。对deque的排序操作,可将deque先复制到vector,排序后在复制回deque。

3。list   (每个元素间用链表相连)访问随机元素不如vector快,随机的插入元素比vector快,对每个元素分配空间,所以不存在空间不够,重新分配的情况,使用内存比vector多

4。set 内部元素唯一,用一棵平衡树结构来存储,因此遍历的时候就排序了,查找也比较快的哦。

5。map 一对一的映射的结合,key不能重复。

6。stack 适配器,必须结合其他的容器使用,stl中默认的内部容器是deque。先进后出,只有一个出口,不允许遍历。

7。queue 是受限制的deque,内部容器一般使用list较简单。先进先出,不允许遍历。

下面是选择顺序容器类型的一些准则 

1.如果我们需要随机访问一个容器则vector要比list好得多 。

2.如果我们已知要存储元素的个数则vector 又是一个比list好的选择。 

3.如果我们需要的不只是在容器两端插入和删除元素则list显然要比vector好 

4.除非我们需要在容器首部插入和删除元素否则vector要比deque好。

5.如果只在容易的首部和尾部插入数据元素,则选择deque.

6.如果只需要在读取输入时在容器的中间位置插入元素,然后需要随机访问元素,则可考虑输入时将元素读入到一个List容器,接着对此容器重新拍学,使其适合顺序访问,然后将排序后的list容器复制到一个vector容器中

 1 如果你需要高效的随即存取,而不在乎插入和删除的效率,使用vector

 2 如果你需要大量的插入和删除,而不关心随即存取,则应使用list

 3 如果你需要随即存取,而且关心两端数据的插入和删除,则应使用deque

9.静态链接库与动态链接库的区别

静态链接库:lib中包含的指令直接包含在生成的.exe中。

动态链接库:dll文件不必包含在.exe文件中,exe文件执行时可以动态的调用和卸载dll文件。

静态链接库不能包含其他的动态链接库和静态库;动态链接库可以包含。

动态链接库:需要调用动态链接库中的函数时,根据函数映射表找到该函数并调入堆栈执行,如果存在多处对该函数的调用,执行时只保留一处拷贝。

静态链接库:存在对lib文件中同一函数的多次调用时,执行时,程序空间中保留多分拷贝,调用依次就保留一份拷贝。

导出函数的声明方式:  

 一种在函数声明类型和函数名之间加上“_declspec(dllexport)”。   

另外一种采用模块定义(.def)文件声明,需要在库工程中添加模块文件,格式如下:    LIBRARY 库工程名称 

EXPORTS 导出函数名  

DLL的调用方式:   

一种静态调用,由编译系统完成对DLL的加载和应用程序结束时DLL的卸载。  

另外一种动态调用,由编程者用API函数加载和卸载DLL(DLL加载—DLL函数地址获取—DLL释放)方式。   

所有库工程编译时必须Release方式:

10.如何实现多线程的同步

http://www.cnblogs.com/jzincnblogs/p/5188051.html

使用Windows API的互斥对象:

使用windows API的临界区对象:

使用Windows API的事件对象:

使用C++标准库的thread、mutex头文件:

11.析构函数为什么要定义为虚函数,深复制与浅复制

delete指向子类对象的基类指针时,如果析构函数不是virtual,则只会调用基类的析构函数,从而造成内存泄漏

12.了解socket编程吗

13.用过ADO吗

14.使用C++封装http协议包

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

haimianjie2012

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值