后端开发相关

文章目录

🍺 C++基础

🍻 [悬空指针 / 野指针] 的区别 ?

🧡 野指针和悬空指针都是指针指向无效内存区域的指针,访问会导致未定义的行为,比如程序崩溃或数据错乱。
🔶 悬空指针:指的是指向已释放内存的指针。为了避免,可以使用智能指针,或在 free / delete 内存后及时将指针置为空。
🔶 野指针:指的是没有经过初始化的指针。为了避免,可以在初始化指针后默认置为空。

🍻 调用 [free] 后指针指向的内存区域的状态 ?

🧡 调用 free 后,指针 p 的值不变。
🔶 调用 free 后,指针 p 所指向内存的值不确定,可能变也可能不变。
🔶 因为调用 free 后,会将指针 p 所指区域标记为已释放状态,可以由 malloc / free 重新申请,但是指针 p 和所指内容不会自动清空。

🍻 频繁 [new / free] 对象会导致的问题 ?

🧡 在使用 new / free 时,由于申请释放内存比较频繁且大小不定,会造成大量的内存碎片影响性能。
🔶 内存碎片多的时候,连续的内存空间会变少,因此当申请比较大的内存时有可能找不到连续内存导致申请失败。
🔶 可以使用内存池来管理内存分配,先分配一定数量和大小的内存块,优先从内存块中分配内存给对象,如果内存块不够用则继续申请新的内存块,有效的减少了内存碎片

🍻 [静态库 / 动态库] 的区别 ?

🧡 静态库将代码静态的编译到可执行文件中,因此可执行文件较大;而动态库是在运行中从共享库中加载所需要的代码,因此可执行文件较小。
🔶 静态库一旦被链接,其中的代码不会发生更改;而动态库可以在程序运行的时候修改或替换。
🔶 静态库在每个可执行文件中都需要一个副本;而动态库可以被多个可执行文件共享,因此比较节省磁盘空间。

🍻 [多态] 是什么 ?

🧡 多态:是指相同的对象收到不同的消息,或者不同的对象收到相同的消息可以产生不同的响应。
🔶 C++ 支持运行时的动态多态和编译时的静态多态。其中动态多态通过虚函数实现,而静态多态通过函数重载实现。

🍻 [动态多态 / 静态多态] 的区别 ?

🧡 C++ 的多态性具体体现在编译和运行两个阶段。编译时的多态为静态多态,在编译时就可以确定所使用的接口。运行时的多态为动态多态,具体使用的接口需要根据运行时的参数对象来决定。
🔶 静态编译主要通过函数重载和模板来实现,函数同名但参数类型和数量不同;动态多态通常通过虚函数来实现,程序运行时会根据父类指针所指对象的类型来调用对应函数。

🍻 [动态多态] 的实现 ?+2

🧡 当编辑器发现父类中有虚函数时,会为每个含有虚函数的类创建一份虚表,虚表里存放着虚函数的入口地址。
🔶 编辑器会在类中保存一个虚表指针,指向所属的虚表。
🔶 当创建子类时,程序会自动调用构造函数,在构造函数中初始化虚表和虚表指针。其中会先调用父类构造函数,为父类对象初始化虚表和虚表指针。之后再调用子类构造函数,为子类对象初始化虚表和虚表指针。
🔶 如果子类对象没有对父类的虚函数重写,那么子类的虚表指针指向的是父类的虚表。如果子类对象对父类的虚函数进行了重写,那么子类的虚表指针指向的是自身的虚表。
🔶 当指向子类的父类指针作为参数传递时,可以根据子类是否对虚函数进行重写而实现动态的调用,实现多态性。

🍻 [重载 / 重写 / 隐藏] 的区别 ?

🧡 函数重载是指在同一定义域中,多个函数同名,但是函数参数列表的数量或类型有所不同。重载不能根据返回值来判断,因为函数重载通过命名倾轧(qingya)来区分同名函数,而这个倾轧技术只与参数列表的类型,顺序有关,与返回值并没什么关系。此外编译器在调用函数的时候,并不知道函数的返回值应该是什么类型。
🔶 函数重写是指在子类中定义与父类中同名,参数列表,返回值均相同的函数,覆盖掉父类中的虚函数。
🔶 函数隐藏是指在子类中定义与父类中同名,参数列表相同的函数,返回值可以不同,它和重写的区别在于同名的函数不是虚函数,因此父类中的同名函数被完全覆盖。

🍻 [空类] 的大小 ?

🧡 空类的大小为 1,因为类的实例化会在内存中分配一块独一无二的地址,编辑器会默认给空类一个字节。
🔶 普通的非空类的大小会根据内存对齐的原则来给变量分配存储空间。
🔶 如果类里面有虚函数,那么需要在类中存储一个指向虚表的虚表指针,64 位系统大小为 8 字节。
🔶 对于继承父类的子类的大小,是父类的大小加上子类成员变量的大小。

🍻 C++11 [新特性] 有哪些 ?

🧡 使用 nullptr 代替了 NULL,引入 auto 和 decltype 实现了类型推导,引入 final 和 override 继承关键字,引入基于范围的 for 循环等。
🔶 引入了匿名函数 lambda 表达式,用来替换独立的函数或函数对象。
🔶 支持自定义类型的列表初始化,初始化代码更加简洁。
🔶 引入了三种智能智能,避免内存忘记释放导致内存泄漏。
🔶 引入了右值引用和 move 语义,减少了不必要的资源拷贝。

🍻 [智能指针] 的种类和作用 ?

🧡 智能指针:本质上是一个类,它用来存储指向动态分配对象的指针,并负责该动态分配对象的释放,避免内存泄漏。当智能指针对象的生命周期结束后,会自动调用析构函数来释放动态分配的资源。
🔶 shared_ptr:多个该智能指针可以指向同一个对象。每当增加一个智能指针指向该对象时,所有的智能指针内部的计数器都会加一,每当减少一个智能指针指向该对象时,所有的智能指针内部计数器都会减一。因此当智能指针内部的引用计数器为零时,则会自动释放动态分配的内存资源。
🔶 unique_ptr:该智能指针独享所指向对象的所有资源。当资源进行转移时,原来的智能指针将被置空,因此 unique_ptr 不支持普通的拷贝和赋值操作,因为此时有两个智能智能指向同一个资源,导致同一内存多次释放。
🔶 weak_ptr:该智能指针主要是为了解决循环引用的问题,此时两个指针指向的内存都无法释放。weak_ptr 是一个弱引用,它指向 shared_ptr 管理的对象而不影响对象的计数。当访问对象时,可以使用 lock 函数来获取指向该对象的 shared_ptr。

🍺 计算机网络

🍻 [三次握手] 的过程 ?

🧡 最开始,客户端和服务端都处于 CLOSE 状态,于是服务端开始监听端口,处于 LISTEN 状态。
🔶 此时客户端请求连接,发送 SYN 报文,进入 SYN_SEND 状态。
🔶 服务端收到 SYN 报文,发送 SYN+ACK 报文表示已收到消息,同意连接,随后进入 SYN_RECV 状态。
🔶 最后当客户端收到 SYN+ACK 报文后,发送 ACK 报文并进入 ESTABLISH 状态,服务端收到 ACK 报文后也进入 ESTABLISH 状态。

🍻 [四次挥手] 的过程 ?

🧡 最开始,客户端和服务端处于 ESTABLISH 状态,此时客户端想要断开,于是发送 FIN 报文给服务端,进入 FIN_WAIT_1 状态。
🔶 服务端收到 FIN 报文后,发送 ACK 报文给客户端,表示收到信息,随后进入 CLOSE_WAIT 状态。
🔶 客户端收到 ACK 报文后,进入 FIN_WAIT_2 状态。
🔶 服务端将待处理数据处理完毕后,向客户端发送 FIN 报文表示同意断开,随后进入 LAST_ACK 状态。
🔶 客户端收到 FIN 报文后,回应 ACK 给服务端,进入 TIME_WAIT 阶段。
🔶 服务端收到 ACK 报文后,直接进入 CLOSE 状态,此时服务端已经关闭连接。
🔶 而客户端需要等待 2MSL 时间,等待完后自动进入 CLOSE_WAIT 状态,关闭连接。

🍻 [get / post] 的区别 ?+2

🧡 get 是获取数据;post 是修改数据。
🔶 get 把请求放在 url 上,通过 ? 分隔 url 和传输数据,不安全;post 把数据放在 http 数据包内,相对安全。
🔶 get 提交的数据量最大为 2k;post 提交的数据量理论上没有限制。
🔶 get 会产生一个 tcp 数据包,浏览器会把 http header 和 data 同时发过去,服务器响应 200;post 会产生两个 tcp 数据包,浏览器先发送 http header,服务器响应 100,再发送 data,服务器响应 200。
🔶 get 请求会被浏览器主动缓存;post 请求不会被浏览器主动缓存,需要手动设置。
🔶 get 请求是幂等的,即多次请求返回相同结果;post 请求不是幂等的。

🍻 [tcp / udp] 的区别 ?

🧡 连接:tcp 是面向连接的协议,传输前需要先建立连接;udp 可以不建立连接直接传输。
🔶 服务对象:tcp 是一对一的点到点服务;udp 支持一对一,一对多,多对一的服务。
🔶 可靠性:tcp 是可靠的,数据可以无差错,有序,完整的传输;udp 是尽最大可能的交付,并不可靠。
🔶 拥塞控制:tcp 有拥塞控制;udp 没有。
🔶 首部开销:tcp 首部长,开销大;udp 首部开销固定只有 8 字节。
🔶 传输方式:tcp 是基于字节流的传输,无边界但是有序;udp 是基于包的传输,有边界但是无序。
🔶 应用场景:tcp 是面向连接且可靠的,因此主要用于像文件传输这样的场景;udp 是无连接不可靠的,但因为其传输快可以用于像音视频通话这样的场景。

🍻 [http / tcp] 的区别 ?

🧡 http 协议对应于应用层,定义的是传输数据内容的规范;tcp 协议对应于传输层,定义的是传输和连接方式的规范。
🔶 http 协议是在 tcp 协议之上建立的,http 在发送请求后通过 tcp 建立连接并发送数据,请求结束后关闭 tcp 连接。
🔶 http 是无状态的短连接;tcp 是有状态的长连接。

🍻 [https / http] 的区别 ?

🧡 http 是超文本传输协议,信息是明文传输,因此存在安全风险;https 解决了 http 不安全的问题,在 tcp 和 http 之间加入了 ssl/tls 协议,使得报文可以加密传输。
🔶 http 建立连接比较简单,tcp 三次握手后就可以建立;https 在 tcp 的三次握手之后,还需要经历 ssl/tls 的握手过程,加密传输。
🔶 两者的默认端口不同,http 默认为 80,https 默认为 443。
🔶 http 不需要数字证书;https 需要申请数字证书认证,来确保服务器的身份是可信的。

🍻 [长连接 / 短连接] 的区别 ?

🧡 概念:长连接是指在完成通信连接后进行数据交换,但是在空闲时仍然维持连接,保持一段时间不关闭;短连接是指建立通信连接进行数据交换后,直接中断连接,等待下次通信时重新连接。
🔶 应用:长连接主要用于操作频繁、连接数不多的情况,比如像数据库连接,因为每次连接需要 tcp 三次握手,频繁的断开连接会非常影响性能;短连接主要用于无频繁操作,连接数较多的情况,比如像 web 网站,因为每个 socket 连接都会占用系统资源,而采用短连接会使连接的并发量大大降低,节省系统资源。

🍻 [长连接] 如何实现 ?

🧡 http 的长连接实现是建立在 tcp 协议的基础上的。
🔶 http 默认是使用短连接的,每进行一次 http 的请求 / 响应后就关闭连接,此时 http 首部字段中的 connection 参数设置为 close。
🔶 可以在 http 首部字段中将 connection 设置为 keep-alive,并设置过期时间为 n 秒,空闲时间超过 n 秒后自动关闭,如果不设置过期时间,那么连接将永久有效。

🍻 [cookie] 是什么 ?

🧡 cookie 是客户端保持状态的方法。
🧡 cookie 是由服务端发送给客户端,并由客户端来保存的一段字符串数据,下次向同一服务端发送请求时会被携带发送。
🔶 cookie 的作用主要是告知服务端多个请求是否来自于同一个客户端,解决了 http 的无状态问题,比如可以用在维持用户登录状态,网页个性化设置等场景。

🍻 [session] 是什么 ?

🧡 session 是服务器保持状态的方法。
🧡 session 存储在服务器上的数据库、文件或内存中。
🔶 每个用户拥有自己对应的 session id 作为哈希表的键值,通过这个 id 可以找到对应的 session 数据,其中保存着用户的操作行为,直到客户端关闭或者 session 超时。
🔶 目前大多数的应用都是通过 cookie 来实现 session 跟踪的,当创建 session 时,服务端会在返回给客户端的 cookie 中记录 session id,根据 session id 来识别请求方。

🍻 [cookie / session] 的区别 ?

🧡 作用范围不同:cookie 保存在客户端;session 保存在服务端。
🔶 存取方式不同:cookie 只能保存 ASCII 数据;session 可以保存任意类型数据。
🔶 有效期不同:cookie 有效期较长,可以长时间保存,比如默认登陆功能;session 有效期较短,客户端关闭或 session 超时都会失效。
🔶 安全性不同:cookie 保存在本地,容易被窃取;session 保存在服务端,总体比较安全。
🔶 存储大小不同:cookie 保存的数据量较少,不超过 4k;session 保存的数据量较多。

操作系统

[epoll] 的原理 ?XXX略XXX

[select / poll / epoll] 的区别 ?+2

🔶 连接数不同:select 的最大连接数有限制,通过 FD_SETSIZE 宏定义,大小是 32 的整数倍;poll 和 select 本质上没有区别,只是最大连接数没有限制,因为它通过链表来存储连接信息;epoll 虽然有连接数限制,但这个数很大,1G 内存可以打开近 10 万的连接。
🔶 IO 效率不同:select 和 poll 都采用轮询的机制,会对 socket 进行线性遍历,在 socket 过多时效率会很低;epoll 是事件驱动的,只有活跃的 socket 才会主动调用 callback 函数,因此 epoll 的效率与 socket 的数量无关,而仅与活跃的 socket 数量有关。
🔶 消息传递方式:select 和 poll 中的消息传递需要将内核态中的消息传递到用户态,涉及内核拷贝动作;epoll 中的消息传递是通过内核用户空间共享同一块内存来实现的。

[socket] 连接是否需要关闭 ?

🔶 socket 连接在网络通信之后,需要在合适的时机关闭,主要是为了释放网络资源,减少资源浪费和避免安全风险。
🔶 socket 如果不关闭,可能会导致资源泄漏,网络阻塞甚至是网络攻击。

[水平触发 / 边缘触发] 的区别 ?

🔶 水平触发 LT:只要缓冲区有数据,就一直触发,直到缓冲区为空。优点是它保证了数据读取的完整性,但是在数据量较大时,需要涉及大量用户态到内核态的切换,十分的消耗系统资源,影响服务器性能。
🔶 边缘触发 ET:是只有监听事件的状态改变,或有事件发生时才会触发。边缘触发一次只能读取部分数据,剩下的数据需要等待下次出发读取,因此不能够确数据读取的完整性,因此需要和非阻塞 IO 配合使用。边缘触发后,非阻塞 IO 循环读取数据,直到缓冲区数据全部读取。优点是只需要触发一次就可以读取缓冲区所有数据,效率比较高,性能也更好。

[用户态 / 内核态] 的区别 ?如何切换 ?

🔶 内核态也叫内核空间,是内核进程所在的区域,主要负责系统运行,硬件交互;用户态也叫用户空间,是用户进程所在的区域,主要负责执行用户程序。
🔶 内核态运行的代码不受任何限制,CPU 可以执行任何命令;用户态的代码需要受到 CPU 的检查,不能直接访问内核数据和程序。
🔶 操作系统在执行用户程序时,大多数时间都是工作在用户态,只有在执行其没有权限的任务时才会切换到内核态。
🔶 切换方式:主动切换有系统调用,当碰到用户态无权限的操作时会切换到内核态;被动切换有异常切换,程序碰到未知异常时会切换内内核处理;被动切换还有外围设备中断,当外围设备发出中断信号时,操作系统会切换到内核进行中断处理。

linux [一切皆文件] 如何理解 ?

🔶 这是因为 linux 将所有的设备、文件、进程都当作文件来处理,统一了对它们的操作方法,使得了 linux 具有很好的灵活性和扩展性。
🔶 好处:👇
🔷 统一的文件操作接口:linux 将所有文件和设备都看作文件,使得对他们的操作方便变得统一和简单,比如复制,移动等操作都可以用相同的命令。
🔷 方便文本处理:可以使用一些命令行工具对文本处理和系统管理,比如可以使用 grep 搜索文件中的特定内容,awk 处理文本数据等。
🔷 方便设备管理:linux 将所有设备看作文件,那么可以使用相同的命令来管理设置,比如用相同命令行管理鼠标,键盘,显示器等。
🔷 安全性:linux 中的每个文件都有都有着自己的访问权限,比如读权限,写权限,执行权限。此外每个文件还有所有者和所属组,使得用户可以精确的控制访问权限,更加的安全。

常用 [gdb] 命令有哪些 ?XXX略XXX

[线程] 崩溃后,[进程] 也会崩溃吗 ?

🔶 如果线程是因为非法访问内存引起的崩溃,那么进程肯定会崩溃,因为进程中各个线程是共享内存的,某个线程的非法访问内存会对其他线程产生很大影响,操作系统直接会让整个进程崩溃。

[进程] 间的 [通信方式] 有哪些 ?

🧡 管道:允许一个进程和拥有公共祖先的另一个进程间进行通信。但是管道通信的效率较低,不适合频繁的数据交换。
🔶 命名管道:允许任意两个进程之间进行通信,通过 mkdifo 来创建命名管道。
🔶 消息队列:消息队列是保存在内核中的消息链表,有写权限的进程可以向队列中添加消息,有读权限的进程可以从队列中取出消息。消息队列中消息体的大小有长度限制,不能传输过大的数据。在消息队列通信的过程中,存在用户态和内核态之间的数据拷贝开销。
🔶 共享内存:共享内存机制把多个进程中的虚拟地址空间映射到相同的物理地址空间中去。这样一个进程写入数据,其他进程立马可以看到,不需要数据的拷贝过程,大大提高了通信效率。但如果多个进程同时修改共享内存,那么可以会发生冲突。
🔶 信号量:信号量是一个整形的计数器,主要用于实现进程间的互斥和同步。信号量的值代表资源的数量,控制信号量的方式有 P 操作和 V 操作,分别发生在进入共享资源,离开共享资源时。
🔶 信号:信号是进程间的一种异步通信机制,可以在任何时候发送信号给某一进程。信号的来源有硬件来源(ctrl+C 终止进程)和软件来源(kill 命令)。
🔶 socket:socket 可以实现跨网络不同主机间进程的通信,也可以实现同主机间不同进程的通信。

[线程] 间的 [通信方式] 有哪些 ?

🔶 线程间的通信目的主要是用于线程同步,所以线程没有像进程通信中的数据交换相关的机制。
🔶 锁机制:包括互斥锁,读写锁,条件变量,等。互斥锁以排他的方式防止同共享数据同一时间被多个线程修改。读写锁允许多个线程同时读数据,但是同一时间只能有一个线程写数据。条件变量以原子的方式阻塞线程,直到某个特定的条件为真则继续执行,通常和互斥锁配合使用。
🔶 wait / notify 等待:当一个线程调用锁对象的 wait 方式时,线程会放弃同步锁进入等待队列,直到其他线程进入同步锁调用 notify 唤醒该线程。
🔶 volatile 共享内存:volatile 具有可见性和有序性,其中可见性就是确保线程间可以进行通信。实现可见性需要两个原则保证,当 volatile 修饰的变量被线程修改时,必须立即刷新到主内存;当线程读取 volatile 修饰的数据时,需要从主内存中读取新值。
🔶 信号量:信号量是一个整形的计数器,可以用于实现线程间的互斥和同步。
🔶 信号:信号是进程间的一种异步通信机制,可以在任何时候发送信号给某一线程。

linux [进程] 退出的方法有哪些 ?

🔶 正常退出:main 函数的 return 返回;调用 exit 函数;调用 _exit 系统接口函数。
🔶 异常退出:向进程发送信号导致进程异常退出,比如键盘的 ctrl+C 终止;代码错误而导致程序运行崩溃的退出。

[死锁] 的条件是什么 ?

🔶 死锁是线程双方都在等待对方释放锁,而无法继续运行的情况。
🔶 互斥条件:一个资源同时只能被一个线程所持久。
🔶 持有并等待条件:线程 A 已持有部分资源,在等待其他资源时已有的资源不会释放。
🔶 不可剥夺条件:线程 A 已持有部分资源,线程 B 无法使用这些被持有的资源,只能等线程 A 释放后才能使用。
🔶 环路等待条件:线程 A 和线程 B 获取资源的顺序形成了回路。比如线程 A 持有资源 1,等待资源 2,线程 B 持有资源 2,等待资源 1。

[栈] 溢出的原因 ?

🔶 函数调用的层次太深:当函数递归调用时,系统需要在栈中保存调用函数中产生的变量以及调用函数的返回地址,层次太深时会导致栈溢出。
🔶 动态申请的内存未释放:当使用 new / malloc 申请动态内存时,需要用 delete / free 来释放。
🔶 数组访问越界:当访问数据的下标越界时会发生内存访问错误。
🔶 指针非法访问:指针存放了一个非法的地址,当访问内存时会发生内存访问错误。

Mysql

Redis

项目

发送了 1000m 数据,对方只收到 100m 的数据,原因是什么 ?

算法

快速排序算法

二分查找算法

string 实现

三个线程循环打印 ABC

HR 面

学校的项目都是自己做的吗 ?

有一件事情要求你提前完成会怎么做 ?

对加班有什么看法 ?

本科的时候除了学习还有什么其他活动 ?

自己主导的项目讲讲难点和具有创新的地方 ?

为什么要转行搞互联网 ?

找工作看重哪些方面 ?

对本公司有什么了解 ?

你未来的工作规划是什么样的 ?

C++ 开发的应用多嘛,主要用在哪些场景 ?

题目来源

🎃海康威视 🎃百度 🎃大华 🎃深信服 🎃百度

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

进击的小老虎丶

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

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

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

打赏作者

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

抵扣说明:

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

余额充值