C++:面经1

浏览器显示当前链接不安全,是为什么呢

  1. 未使用HTTPS加密‌:如果网站使用的是HTTP协议而不是HTTPS协议,数据传输没有加密,浏览器会标记该网站为不安全。HTTPS是一种安全的连接协议,通过SSL/TLS证书对数据进行加密,保护信息免受窃听或篡改。

  2. SSL证书有问题‌:SSL证书可能已经过期、有误、不匹配网站名,或者不是由知名机构签发的。这种情况下,浏览器无法验证证书的有效性,因此会显示不安全。

  3. 网站被标记为危险‌:如果有人报告网站存在欺诈、病毒、钓鱼等问题,网站可能会被标记为不安全。这需要网站管理员证明网站已安全,并全面检查网站以清除隐患。

  4. 网页里混杂了非HTTPS的内容‌:即使网站主地址使用了HTTPS,但如果网页中包含通过HTTP链接加载的图片、脚本等资源,浏览器仍会显示不安全。这是因为不安全的资源可能被劫持,成为攻击的入口点。

  5. 存在安全漏洞‌:网站可能存在SQL注入、跨站脚本(XSS)、跨站请求伪造(CSRF)等安全漏洞,这些漏洞可能被黑客利用来攻击网站或盗取用户数据,虽然这类问题不会直接导致“不安全”警告,但长期存在会增加网站被标记的风险。

解决这些问题的方法包括:

  • 启用HTTPS并安装SSL证书,确保所有访问均通过加密连接。
  • 定期检查并更新SSL证书,确保及时续期或处理证书问题。
  • 清理混合内容,确保所有资源通过HTTPS加载。
  • 证明网站安全,全面检查并清除安全隐患。
  • 保持服务器软件更新,及时修补已知的安全漏洞,使用防火墙和其他安全措施保护服务器不受未授权访问。

通过上述方法,可以有效解决浏览器显示当前连接不安全的问题,提高网站的安全性‌。

HTTPS和HTTP的区别

​ ‌HTTPS和HTTP的主要区别在于安全性​、加密、身份验证、连接建立过程和端口使用。‌

  • 安全性‌:HTTP是一种明文传输协议,不提供任何数据加密或验证,因此存在很大的安全风险,尤其是对于敏感信息如用户名、密码等。相比之下,HTTPS在HTTP的基础上增加了SSL/TLS层,利用对称加密非对称加密技术,对数据进行加密、解密、签名和验证,保证了数据的机密性、完整性和身份真实性,防止数据被第三方窃取或篡改‌。

  • 加密算法‌:HTTPS采用对称加密与非对称加密的混合加密方式,确保信息的机密性,同时使用摘要算法为数据生成独一无二的「指纹」校验码,确保数据的完整性。此外,通过数字证书来验证服务器的身份,防止中间人攻击‌。

  • 身份验证‌:HTTPS使用数字证书来验证服务器的身份,确保数据传输的可信性。这包括将服务端的公钥放入到CA数字证书中,解决了服务端被冒充的风险‌。

  • 连接建立过程‌:HTTPS在TCP三次握手之后,还需进行SSL/TLS的握手过程,才可进入加密报文传输。这包括客户端和服务器之间的密钥交换、认证以及协商加密参数等步骤,以确保安全通信‌。

  •  

    端口使用‌:HTTPS和HTTP使用不同的默认端口。HTTP使用80端口,而HTTPS使用443端口。这一差异使得HTTPS连接更容易在网络中被识别和区分‌。

为什么HTTPS要更安全‌:

HTTPS之所以更安全,是因为它通过SSL/TLS协议提供了数据加密、身份验证和数据完整性保护。这些安全措施可以防止数据在传输过程中被截获、篡改或冒充,从而保护用户的隐私和安全。此外,HTTPS还通过数字证书验证服务器的身份,进一步增强了安全性,防止了中间人攻击的可能性‌。

聚簇索引跟非聚簇索引的区别?回表是什么情况?非聚簇索引一定会回表吗?

聚集索引选取规则:

  • 如果存在主键,主键索引就是聚集索引。
  • 如果不存在主键,将使用第一个唯一(UNIQUE)索引作为聚集索引。
  • 如果表没有主键,或没有合适的唯一索引,则InnoDB会自动生成一个rowid作为隐藏的聚集索引。

回表查询: 先到二级索引中查找数据,找到主键值,然后再到聚集索引中根据主键值,获取数据的方式,就称之为回表查询。

尽量使用覆盖索引,减少select *。  覆盖索引是指查询使用了索引,并且需要返回的列,在该索引中已经全部能够找到 。

索引什么时候会失效?

  • 1.联合索引不符合最左前缀法则。
  • 2.范围查询使用>或者<时失效,最好用>=或者<=。
  • 3.字符串不加引号。
  • 4.前缀模糊查询。
  • 5.or连接的两个列中至少有一个没有索引。
  • 6.MySQL评估使用索引比全表更慢。

自增id有时候有影响吗

SQL自增ID在某些情况下确实可能带来一些影响。

首先,自增ID的一个潜在问题是它们不具有连续性。如果在数据表中删除了某些记录,自增ID的间隙会导致ID号不连续,这可能在某些应用场景中造成不便。例如,如果需要一个连续的ID序列来进行某些操作,自增ID可能无法满足这一需求‌。

其次,当多个表合并时,自增ID可能导致ID重复的问题。虽然单个表中自增ID能保证唯一性,但在多个表合并的情况下,由于每个表独立生成ID,合并后可能会出现ID重复的情况‌。

最后,某些数据库管理系统(DBMS)在重启时可能会重置自增ID的起始值,导致ID“断开”。例如,SQL Server在某些版本中,重启实例时自增ID的起始值会跳过一定的数值,如整数数据类型可能会跳过1000,大整数数据类型可能会跳过10000。这可能导致ID的不连续性,尤其是在对ID的连续性有严格要求的应用中‌。

综上所述,虽然自增ID在大多数情况下能够满足基本的需求,但在特定场景下,如需要高度连续性的ID、多表合并、分布式数据库应用或对DBMS重启后的行为有特定要求时,自增ID可能不是最佳选择。

binlog、undolog、redolog的区别

binlog、undolog、redolog‌在MySQL数据库中扮演着不同的角色,各有其独特的功能和用途。以下是它们之间的主要区别:

binlog(二进制日志)‌:

  • 设计目标‌:记录对数据库执行的所有更改的写操作,包括数据、表结构、索引等的变更。不包含SELECT、SHOW等查询操作,因为这些操作不修改数据。
  • 应用场景‌:主要用于主从复制和数据恢复。binlog记录了所有对数据库的更改操作,因此可以用于从备份中恢复数据,或者在主从复制中确保从数据库与主数据库的数据一致性。
  • 数据格式‌:binlog有三种格式,分别是STATMENT、ROW和MIXED。这些格式决定了如何记录更改操作,例如,ROW格式基于行级别的更改进行记录,而STATMENT格式则基于SQL语句进行记录。

undolog‌:

  • 功能‌:用于帮助事务回滚及实现MVCC(多版本并发控制)的功能。它记录了事务执行过程中旧值的备份,以支持事务的回滚操作,并确保事务的隔离性和并发访问的一致性。
  • 触发时机‌:在事务执行期间,undolog记录了事务对数据库进行的修改操作的撤销信息,用于实现事务的回滚和并发控制。

redolog‌:

  • 功能‌:用于记录数据库的物理变更操作,例如数据页的修改。它以顺序方式记录,通常是追加写入磁盘上的日志文件。在数据库崩溃时,通过重做日志的回放来恢复已提交的事务所做的修改操作。
  • 触发时机‌:在事务提交之前或事务发生崩溃时,redolog缓冲区中的日志将被刷新到磁盘上的RedoLog文件中,以确保持久性和在崩溃后的数据恢复。

快速读跟当前读的区别?

‌InnoDB的快照读和当前读的主要区别在于是否加锁、读取的数据版本以及适用场景。

  • 是否加锁‌:快照读不会给任何行加锁,​ 它基于MVCC(多版本并发控制)和undolog(回滚日志)  ​来实现,通过创建一个read view(可见性视图)来判断哪些数据版本对当前事务可见。当前读则会加锁,它会实时反映数据库的最新状态,通过加锁来保证在事务进行期间读取的数据不会被其他事务修改。
  • 读取的数据版本‌:快照读读取的是某个时间点的数据快照,这个快照是在事务开始时创建的,因此在事务执行期间,即使其他事务修改了数据,当前事务看到的仍然是事务开始时的数据状态。当前读则读取的是当前最新的数据,不加锁的简单SELECT操作也属于快照读,而在当前读模式下,每次读取的都是当前最新的数据。
  • 适用场景‌:快照读适用于查询数据的操作,如SELECT等,因为它允许读写操作并发进行,不会阻塞其他事务的修改。当前读则主要用于修改数据的操作,如UPDATE、DELETE、INSERT等,以及对数据加锁以保证数据的一致性。

总结来说,快照读通过不加锁的方式提供了一致性非锁定读取,适用于查询操作,而当前读通过加锁的方式保证了读取数据的最新性和一致性,适用于需要保证数据一致性的修改操作‌。

虚函数和纯虚函数的区别

  • ‌虚函数‌:虚函数是指被virtual关键字修饰的成员函数。它在‌基类中定义,并在‌派生类中被重新定义以实现多态性。虚函数通常有一个基本的实现,可以被派生类继承或覆盖。
  • ‌纯虚函数‌:纯虚函数是一种特殊的虚函数,它在基类中没有实现,派生类必须提供自己的实现。纯虚函数通过在函数声明末尾使用= 0标记来指定。包含纯虚函数的类是抽象类,不能直接实例化。

STL 容器原理和底层结构

‌STL(Standard Template Library)容器是C++标准库的一部分,提供了一系列常用的数据结构和算法模板,用于处理数据。STL容器主要包括顺序容器、关联容器、容器适配器等,每种容器都有其特定的底层结构和用途。

顺序容器‌:

  • vector‌:底层由动态数组实现,存储空间连续,支持随机访问迭代器,尾部插入/删除效率高,但中间和头部插入/删除效率低。适用于需要随机访问且频繁在尾部进行操作的情况。
  • deque‌(双端队列):底层由双向队列实现,存储空间连续,支持随机访问迭代器,头部和尾部插入/删除效率高,中间插入/删除效率低。适用于需要随机访问且频繁在首部和尾部进行操作的情况。
  • list‌(双向链表):底层由双向链表实现,存储空间不连续,不支持随机访问迭代器,任意位置插入/删除效率高。适用于需要在任意位置频繁进行插入和删除操作的情况。

关联容器‌:

  • map‌ 和 ‌set‌:基于红黑树实现,提供键值对的存储,自动排序。适用于需要按键值快速查找的场景。
  • multimap‌ 和 ‌multiset‌:与map和set类似,但允许键值重复。适用于需要存储多个相同键值的情况。
  • unordered_map‌ 和 ‌unordered_set‌:基于哈希表实现,提供快速的查找操作。适用于对查找速度要求较高的情况。
  • unordered_multimap‌ 和 ‌unordered_multiset‌:与unordered_map和unordered_set类似,但允许键值重复。

容器适配器‌:

  • stack‌、‌queue‌、‌priority_queue‌:这些容器适配器基于已有的容器构建,提供了特定数据结构的接口。例如,stack基于deque或vector实现,提供了后进先出(LIFO)的数据结构。

Socket TCP 客户端和服务器端编写流程

为什么要有虚拟内存,是如何实现的

虚拟内存的出现主要是为了解决物理寻址的多个问题,包括安全性、同时运行多个程序的困难、用户程序大小的限制等。‌虚拟内存的实现依赖​ 于内存管理单元(MMU)和页表​机制,通过将物理内存划分为固定大小的页框,并将虚拟内存划分为页,利用页表来映射虚拟地址到物理地址。当物理内存不足时,虚拟内存系统通过页面置换算法将部分数据换出到磁盘,需要时再换入,从而保证程序的连续地址空间需求。

解决物理寻址的问题‌:

  • 不安全性‌:物理寻址直接暴露操作系统的地址给用户程序,可能导致操作系统被破坏。
  • 同时运行多个程序的困难‌:多个程序直接引用物理地址容易相互干扰。
  • 用户程序大小的限制‌:受限于物理内存大小,即使应用程序大小小于物理内存,也需要虚拟内存技术来支持更大应用程序的运行。

虚拟内存的实现原理‌:

  • 虚拟地址空间‌:每个进程都有一个独立的虚拟地址空间,这个空间是连续的,对进程来说是唯一的。
  • 物理内存与页框‌:物理内存被划分为固定大小的页框,称为页。
  • 页表‌:用于映射虚拟地址到物理地址的数据结构,每个进程都有自己的页表。
  • 地址转换‌:通过内存管理单元(MMU)将虚拟地址转换为物理地址,包括虚拟地址分解、查找页表、计算物理地址等步骤。
  • 页面置换算法‌:当物理内存不足时,使用页面置换算法将部分数据换出到磁盘,需要时再换入。

TCP怎么知道对方断线了

TCP服务器可以通过以下几种方式来判断客户端是否断线:

  • 超时机制:服务器可以设置一个超时时间,当服务器在指定时间内没有收到客户端的消息时,可以认为客户端已经断线。如果超过了设定的超时时间,服务器可以主动断开与该客户端的连接。

  • 心跳包机制:服务器可以定期向客户端发送心跳包,用来判断客户端是否还活跃。如果一段时间内没有收到客户端的心跳包,服务器可以认为客户端已经断线。

  • 探测机制:服务器可以向客户端发送探测消息,如果客户端无法正常响应或不存在,服务器可以认为客户端已经断线。

  • TCP的keep-alive机制:TCP协议本身提供了keep-alive机制,通过保持长时间的空闲连接,服务器可以判断客户端是否还处于连接状态。当服务器长时间没有收到客户端的确认包时,可以认为客户端已经断线。

需要注意的是,仅仅通过一次判断客户端是否断线是不够的,因为网络中断、客户端程序异常等原因都可能导致连接中断。为了保证可靠性,服务器应该通过多种方式来判断客户端是否断线,并且在判断客户端断线后及时处理,关闭相应的连接资源,避免资源的浪费和影响服务器的性能。

静态链接和动态链接的区别

链接即为编译(包含预编译,编译和汇编过程)完成之后的过程,此过程又分为静态链接和动态链接两种方式

1、静态链接
       静态链接就是在生成可执行文件的时候(链接阶段),把所有需要的函数的二进制代码都包含到可执行文件中去。因此,链接器需要知道参与链接的目标文件需要哪些函数,同时也要知道每个目标文件都能提供什么函数,这样链接器才能知道是不是每个目标文件所需要的函数都能正确地链接。如果某个目标文件需要的函数在参与链接的目标文件中找不到的话,链接器就报错了。

优点:

  • 在程序发布的时候就不需要依赖库,也就是不再需要带着库一块发布,程序可以独立执行。
  • 代码装载速度快,执行速度略比动态链接库快;

缺点:

  • 浪费内存空间。在多进程的操作系统下,同一时间,内存中可能存在多个相同的公共库函数。
  • 程序的开发与发布流程受模块制约。 只要有一个模块更新,那么就需要重新编译打包整个代码。

2、动态链接

       在编译的时候不直接拷贝可执行代码,而是通过记录一系列符号和参数,在程序运行或加载时将这些信息传递给操作系统,操作系统负责将需要的动态库加载到内存,然后程序在运行到指定的代码时,去共享执行内存中已经加载的动态库可执行代码,最终达到运行时连接的目的。

优点:

  • 解决了静态链接的缺陷,更适应现代的大规模的软件开发。

缺点:

  • 结构复杂。对于静态链接来说,系统只需要加载一个文件(可执行文件)到内存即可,但是在动态链接下,系统需要映射一个主程序和多个动态链接模块,因此,相比于静态链接,动态链接使得内存的空间分布更加复杂。
  • 由于是运行时加载,可能会影响程序的前期执行性能

操作系统死锁和预防

死锁是操作系统中多个进程因互相等待对方手里的资源而导致的永久阻塞现象,而死锁预防则是通过设计资源分配算法,确保不发生死锁的行为过程。

死锁的发生需要满足四个必要条件:互斥条件、占有并等待条件、不可剥夺条件和循环等待条件。互斥条件指的是至少有一个资源必须同时只能被一个进程使用;占有并等待条件意味着一个进程在等待其他资源时必须保持对已有资源的占有;不可剥夺条件表明已分配的资源不能被其他进程强行夺走;循环等待条件则描述了一种进程资源的循环等待链存在的情况。为了预防死锁,可以采取以下策略:

  1. 破坏互斥条件‌:虽然这通常不可行,因为某些资源必须互斥使用以保证系统安全。
  2. 破坏占有并等待条件‌:通过要求进程在开始时就申请所有所需资源(一次性分配方案),或者要求进程在申请新资源前释放已占有的资源。
  3. 破坏不可剥夺条件‌:允许已分配资源的临时剥夺,即允许其他进程在特定条件下抢占资源。
  4. 破坏循环等待条件‌:通过资源分配的顺序进行规划,避免形成循环等待链。

死锁的处理策略除了预防之外,还包括避免死锁(通过算法确保系统始终处于安全状态)和检测并解除死锁(允许死锁发生,但由操作系统负责检测并采取措施解除)。预防死锁的策略虽然简单有效,但可能会对进程的约束过多,导致资源利用率下降或造成资源浪费。因此,在实际应用中需要权衡各种策略的优缺点,选择最适合当前系统需求的方法。

在C和C++中static的基本作用

  • 静态局部变量:在函数内部声明的静态变量,在第一次执行到该变量定义时被初始化,并在函数调用结束后不会被销毁,而是保持其值直到下次调用。
  • 静态全局变量:在全局作用域声明的静态变量只在其声明的文件内可见,从而避免了全局命名空间的污染。
  • 静态函数:在函数前加static关键字,可以使函数只在定义该函数的文件内可见。
  • 静态成员变量和函数:在类中声明的静态成员变量和函数属于类本身,而不是任何特定的对象。

操作系统发生缺页时的做法

操作系统在发生缺页时,会执行以下操作:修改页表、磁盘I/O、分配页框。

缺页中断发生后,操作系统需要执行一系列操作来处理缺页情况。首先,操作系统会在内存中找到空闲的页框并分配给需要访问的页面。如果没有空闲的页框,操作系统会调用页面置换算法来选择一个页面将其移出内存,以便为即将调入的页面腾出空间。接着,操作系统通过设备驱动程序执行磁盘I/O操作,将位于外存(通常是磁盘)上的页面调入内存。页面调入内存后,需要修改页表,将页表中代表该页是否在内存的标志位(如存在位或有效位)设置为“真”,并将物理页框号填入相应位置。如果需要,还会修改其他相关表项。

此外,如果选定的页框包含的数据需要被写回到磁盘,因为该页框的数据已经修改,操作系统会先将数据写回磁盘,然后标记页框为可用状态。在处理完这些操作后,缺页中断处理程序返回,继续程序的执行。这个过程确保了系统能够有效地管理内存资源,同时保证程序的连续执行不受缺页中断的影响‌。

C++ 虚函数虚表工作原理

在C++中,虚函数和虚表是实现多态的核心机制。每个包含至少一个虚函数的类都有一个与之关联的虚表(vtable),该虚表是一个指针数组,其中的每个指针都指向类的虚函数实现。

虚表由编译器自动生成,并在类的构造函数中初始化。当通过基类指针调用派生类的虚函数时,编译器会使用指针指向的对象的vtable来解析正确的函数地址。

C++左值引用和右值引用

在C++中,有两种引用类型:左值引用和右值引用。

  1. 左值引用(Lvalue Reference):左值引用通常指向一个对象的身份,它用于使已存在的对象或变量能够被引用。左值引用时,必须初始化为一个左值(可以是变量或者成员)。

  2. 右值引用(Rvalue Reference):右值引用时C++11引入的特性,用于支持临时对象的引用。右值引用只能绑定到一个将要销毁的对象。通常右值引用用于支持移动语义和完美转发。

在C++11之后,可以通过std::move将左值转为右值。

用户态转到内核态的方式

用户态转到内核态的方式主要有三种:系统调用、异常、和外围设备中断。

  • 系统调用‌:这是用户态进程主动要求切换到内核态的一种方式。用户态进程通过系统调用申请使用操作系统提供的服务程序完成工作。系统调用的机制其核心是使用了操作系统为用户特别开放的一个中断来实现,例如Linux的int 80h中断。通过系统调用,用户态程序可以请求内核执行特权操作,从而实现用户态到内核态的切换。
  • 异常‌:当CPU在执行运行在用户态下的程序时,发生了某些事先不可知的异常,这时会触发由当前运行进程切换到处理此异常的内核相关程序中,也就转到了内核态。例如,缺页异常是一种常见的异常情况,当程序试图访问的页面不在内存中时,就会触发缺页异常,导致CPU从用户态切换到内核态。
  • 外围设备中断‌:当外围设备完成用户请求的操作后,会向CPU发出相应的中断信号。这时CPU会暂停执行下一条即将要执行的指令,转而去执行与中断信号对应的处理程序。如果先前执行的指令是用户态下的程序,那么这个转换的过程自然也就发生了由用户态到内核态的切换。例如,硬盘读写操作完成时,系统会切换到硬盘读写的中断处理程序中执行后续操作。

这三种方式是系统在运行时由用户态转到内核态的最主要方式,其中系统调用可以认为是用户进程主动发起的,而异常和外围设备中断则是被动的。通过这些方式,可以实现用户态和内核态之间的切换,从而使得用户程序能够执行系统调用、处理异常或响应外围设备的中断信号‌

SQL索引类型

SQL索引类型主要有以下几种:

  • 唯一索引(UNIQUE INDEX):保证索引列的值必须唯一,允许有空值。
  • 主键索引(PRIMARY KEY):一种特殊的唯一索引,用于唯一标识表中的每一行,不允许有空值,一个表只能有一个主键。
  • 全文索引(FULLTEXT INDEX):用于MyISAM引擎,当需要快速检索大量文本时使用。
  • 组合索引(COMPOSITE INDEX):在多个列上创建的索引。

索引优化会使用到的索引:

  • 聚集索引(CLUSTERED INDEX):根据索引列排序表中的数据。
  • 非聚集索引(NONCLUSTERED INDEX):与聚集索引相对,非聚集索引不直接排序表中的数据。

进程与线程的区别

  • (1)调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位
  • (2)并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行
  • (3)拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源.
  • (4)系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值