对最近的面试遇到问题的查漏补缺

1.函数一直递归会有什么影响?如何优化:

答:会造成栈溢出,需要注意的是即使递归函数不传参也会导致栈的溢出。

原理:因为函数递归时,栈里保存了上一次递归的函数的状态,不仅仅是参数或者局部变量,哪怕没有参数或局部变量也会溢出。因为栈里至少保存了上一次递归函数的返回地址。

å¨è¿éæå¥å¾çæè¿°

优化方法:写成循环,或者写成尾递归(其实就是循环),让编译器进行尾递归的优化。

2.函数中死循环会怎么样?,如果是多线程环境下某一个线程死循环了呢?

1.造成程序或线程对cpu资源的浪费: 例如下图的死循环,程序一直占用着25%以上的cpu。2.如果涉及多线程,那么可能会造成死锁:

例如:线程1加锁后进入死循环,无法释放锁,线程2继续加锁时,线程2被系统挂起。

解决:使用Sleep(10),可以看到sleep之后对资源的占用减少了很多。当然更好的解决方法是在一开始就设置好跳出的条件,达到条件后break。对于多线程的情况,需要避免其他线程与包含死循环的线程使用同一个锁。

3.文件指针和平常指针的区别?

文件指针即指向文件的指针

文件分为:

根据文件的读写方式

  1. 随机文件 : 对这类文件中的数据读写是随机的,只要按照相关函数对所要读写的文件进行定位,也就是说:允许跳跃式地对所需的文件位置的数据进行处理。
  2. 顺序文件: 对这类文件中的数据读写是按照顺序进行的,如果要对文件中某个位置的数据进行读写操作,就必须对它前面的数据进行操作,也就是说:不允许跳跃式地对所需的文件位置的数据进行处理。

根据文件的存储方式

  1. 文本文件(AscII码)2.2进制文件

根据存储介质:

1.磁盘文件 2.设备文件(打印机,显示器,键盘等)

4.线程的同步和异步

同步:就是发出一个功能调用时,在没有得到结果之前,该调用就不返回或继续执行后续操作。譬如:十个窗口同时卖票,1号窗口卖第10张,那么其他窗口就不能卖第十张,一般通过互斥锁实现同步。

异步:调用者在没有得到结果之前,就可以继续执行后续操作。 看完同步线程这就好理解了,微信肯定开了好多线程。譬如qq聊天,你可以跟一个人视频的同时,和另一个人文字聊天,或者你给你一个人发文件,不需要等文件发送完成就能继续聊天。

并发与并行:并发重点指的是程序的设计结构,而并行指的是程序运行的状态。并发编程,是一种将一个程序分解成小片段独立执行的程序设计方法。

并发:cpu同一时间段内可以交替处理多个操作;

并行:cpu同一时间点可以同时处理多个操作;

多进程并发:通过进程间的通信;多线程并发:线程间的同步异步,加锁等方式

5.野指针问题,delete 指针后为什么需要置为NULL

首先delete指针只是编译器释放该指针所指向的内存空间(该空间可以给其他变量使用),而不会删除这个指针本身。这可能会导致后续申请指针时,系统新建的指针指向的地址可能会跟delete掉的指针相同,此时如果修改delete掉的指针的内容就会导致对新建的指针内容的修改。

所以为了防止这种情况的发生,需要delete掉后立即置为NULL(避免变成野指针),同时在新建指针的时候需要判断新建的指针是否为NULL,为NULL才是申请成功。

对null的delete可以无数次,因为delete会直接跳过NULL

野指针的概念:野指针指向一个已删除的对象或不可用的地址的指针。

  • 指针变量中的值是非法的内存地址,进而形成野指针。
  • 野指针不是NULL指针,是指向不可用内存地址的指针。

出现原因:

  • 局部指针变量没有被初始化为NULL或别的值(导致指针指向的值随机)。
  • 指针所指向的变量超出其作用域(返回局部变量和局部数组,因为局部变量和数组的内存会被释放)。
  • 使用已经释放(delete)过的指针。
  • 进行了错误的指针运算。,越界?

解决或避免:delete后置为NULL,新建指针时判断是否为NULL,不是则释放并置为NULL,尽量不使用超出作用范围的指针

什么是内存泄露,智能指针:

内存泄漏:

就是指动态分配的内存未释放或者无法释放,但是原本指向这块内存的指针却失去了对这块内存的控制,导致内存的浪费。

智能指针可以解决内存泄露的问题,因为用完后会自动释放,智能指针通过一个引用计数器去记录变量被引用的情况。当最后一个引用被销毁时,系统自动释放该指针。

智能指针的作用是管理一个指针,因为存在以下这种情况:申请的空间在函数结束时忘记释放,造成内存泄漏。使用智能指针可以很大程度上的避免这个问题,因为智能指针就是一个类,当超出了类的作用域是,类会自动调用析构函数,析构函数会自动释放资源。所以智能指针的作用原理就是在函数结束时自动释放内存空间,不需要手动释放内存空间。

6.TCP的3次握手,4次挥手,为什么3次握手而不是两次?

3次握手:

C-> SYN(x) -> S

S->SYN(y)/ACK(x+1)->C

C->ACK(y+1)->S

  • 1.客户端发送syn0给服务器
  • 2.服务器收到syn0,回复syn1,ack(syn0+1)
  • 3.客户端收到syn1,回复ack(syn1+1)

4次挥手:

C->FIN((x),ACK(y))->S

S->ACK(x+1)->C

S->FIN(y)->C

C->ACK(y+1)->S

为什么不是2次握手?

两次不可以:tcp是全双工通信,两次握手只能确定单向数据链路是可以通信的,并不能保证反向的通信正常

握手不用四次:
本来握手应该和挥手一样都是需要确认两个方向都能联通的,本来模型应该是:
1.客户端发送syn0给服务器
2.服务器收到syn0,回复ack(syn0+1)
3.服务器发送syn1
4.客户端收到syn1,回复ack(syn1+1)
因为tcp是全双工的,上边的四部确认了数据在两个方向上都是可以正确到达的,但是2,3步没有没有上下的联系,可以将其合并,加快握手效率,所有就变成了3步握手。

挥手为什么要四次?

4)为什么TCP协议终止链接要四次?

1、当客户端确认发送完数据且知道服务器已经接收完了,想要关闭发送数据口(当然确认信号还是可以发),就会发FIN给服务器。

2、服务器收到客户端发送的FIN,表示收到了,就会发送ACK回复。

3、但这时候服务器可能还在发送数据,没有想要关闭数据口的意思,所以服务器的FIN与ACK不是同时发送的,而是等到服务器数据发送完了,才会发送FIN给客户端。

4、客户端收到服务器发来的FIN,知道服务器的数据也发送完了,回复ACK, 客户端等待2MSL以后,没有收到服务器传来的任何消息,知道服务器已经收到自己的ACK了,客户端就关闭链接,服务器也关闭链接了。

TCP如何保证其可靠性:

1)序列号、确认应答、超时重传

数据到达接收方,接收方需要发出一个确认应答,表示已经收到该数据段,并且确认序号会说明了它下一次需要接收的数据序列号。如果发送发迟迟未收到确认应答,那么可能是发送的数据丢失,也可能是确认应答丢失,这时发送方在等待一定时间后会进行重传。这个时间一般是2*RTT(报文段往返时间)+一个偏差值。

(2)窗口控制与高速重发控制/快速重传(重复确认应答)

TCP会利用窗口控制来提高传输速度,意思是在一个窗口大小内,不用一定要等到应答才能发送下一段数据,窗口大小就是无需等待确认而可以继续发送数据的最大值。如果不使用窗口控制,每一个没收到确认应答的数据都要重发。

使用窗口控制,如果数据段1001-2000丢失,后面数据每次传输,确认应答都会不停地发送序号为1001的应答,表示我要接收1001开始的数据,发送端如果收到3次相同应答,就会立刻进行重发;但还有种情况有可能是数据都收到了,但是有的应答丢失了,这种情况不会进行重发,因为发送端知道,如果是数据段丢失,接收端不会放过它的,会疯狂向它提醒......

(3)拥塞控制

如果把窗口定的很大,发送端连续发送大量的数据,可能会造成网络的拥堵(大家都在用网,你在这狂发,吞吐量就那么大,当然会堵),甚至造成网络的瘫痪。所以TCP在为了防止这种情况而进行了拥塞控制。

慢启动:定义拥塞窗口,一开始将该窗口大小设为1,之后每次收到确认应答(经过一个rtt),将拥塞窗口大小*2。

拥塞避免:设置慢启动阈值,一般开始都设为65536。拥塞避免是指当拥塞窗口大小达到这个阈值,拥塞窗口的值不再指数上升,而是加法增加(每次确认应答/每个rtt,拥塞窗口大小+1),以此来避免拥塞。

将报文段的超时重传看做拥塞,则一旦发生超时重传,我们需要先将阈值设为当前窗口大小的一半,并且将窗口大小设为初值1,然后重新进入慢启动过程。

快速重传(可以看做是对简单的拥塞避免的改进):在遇到3次重复确认应答(高速重发控制)时,代表收到了3个报文段,但是这之前的1个段丢失了,便对它进行立即重传。

然后,先将阈值设为当前窗口大小的一半,然后将拥塞窗口大小设为慢启动阈值+3的大小。

这样可以达到:在TCP通信时,网络吞吐量呈现逐渐的上升,并且随着拥堵来降低吞吐量,再进入慢慢上升的过程,网络不会轻易的发生瘫痪。

 

5. 纯虚函数的作用

纯虚函数可以提供抽象类的功能,抽象类则通常提供统一接口的功能,强迫继承它的派生类各自实现符合自己特点的具体功能,并且一定要有这样的功能,这对于设计和架构非常有用

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

溯夜流云

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

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

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

打赏作者

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

抵扣说明:

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

余额充值