1、gcc,g++,gdb常用命令
首先了解gcc,g++的区别。要先知道我们写的源代码是如何被编译器运行的。大概有四个阶段:
预处理:处理宏定义等宏命令,删除空格等,生成后缀为“.i”的文件  
编译:将预处理后的文件转换成汇编语言,生成后缀为“.s”的文件
汇编:由汇编生成的文件翻译为二进制目标文,生成后缀为“.o”的文件
连接:多个目标文件(二进制)结合库函数等综合成的能直接独立执行的执行文件——生成后缀为“.out”的文件(exe文件)。
gcc无法进行库文件的连接;而g++则能完整编译出可执行文件。前三个阶段g++也是调用gcc实现的。
简单来说gcc是C语言编译器,g++是C++语言编译器。但是事实上,二者都可以编译c或cpp文件。区别在于,对于 .c和.cpp文件,gcc分别当做c和cpp文件编译,g++则统一当做cpp文件编译。
gdb调试是一个功能强大的命令调试程序,也就是一个debug的工具。
安装gdb: sudo apt install gdb
生成可执行代码:gcc test.c -g -o test或者g++ -g test.cpp -o test(注意添加-g参数,才可以调试)
进入gdb调试:gdb ./test

**list:**查看源代码,默认显示10行,可以修改。后面可以加文件名:行号,显示指定文件的以那一行为中心的附近的代码。这个很重要,因为我们需要观察源代码来了解程序逻辑,知道在哪里设置断点等。

插入断点:b 行号(或者函数入口处) 显示断点:info break 删除断点:delete 断点号
知道如何使用断点很重要,这样我们才知道程序中变量的值是如何变化的。
watch 可以用来监视一个变量或者一段内存,当这个变量或者该内存处的值发生变化时,GDB 就会中断下来。被监视的某个变量或者某个内存地址会产生一个 watch point(观察点)。这用于我们想要观察一个变量是否改变,如果一句句地调试太慢了。
关于调试还有**setp[n]和next[n]**两个但不调试命令,二者都代表每隔n行就自动断点,但是前者遇到函数会进入函数体执行,后者则会把函数执行完出来,整个函数体当成是一行。
知道了断点之后,我们可以用run命令运行程序,在断点处会中断,我们进行查看相应的变量的操作,再用continue或者go继续向下执行。

接下来很重要的一部分就是如何查看变量的值、地址、寄存器的值等操作。
查看变量的值**:print/p**. p 变量名,就可以查看变量的值。p/a按十六进制显示,p/c按字符显示等。也可以用display来显示变量的值,display在每次断点都会自动显示,不需要每次都p了,更方便。

查看内存地址的值:x/<n/f/u> n代表往后显示几个地址的内容,f代表显示的格式,比如十六进制十进制浮点数等,如果址所指的是字符串,那么格式可以是s,如果地十是指令地址,那么格式可以是i。u代表指定的字节作为一个值,默认是4个字节。

查看寄存器的值**:info registers**查看所有寄存器的情况。也可以使用print命令来访问寄存器的情况,只需要在寄存器名字前加一个$符号就可以了。如:p $eip。寄存器中可能存放了下一条指令的地址、函数返回地址、堆栈地址等,很重要。

**set args [arguments]:**重新指定被调试程序的命令行参数。show args显示被调试程序的命令行参数。这对于程序参数的相关调试有用。

2、http和https
HTTP,超文本传输协议,规定了浏览器和服务器之间数据传输的规则。HTTP 是应用层协议,它以 TCP(传输层)作为底层协议,默认端口为 80。
http的通信过程:服务器在80端口等待客户的请求;接着浏览器发起到服务器的TCP连接,服务器接受TCP连接,然后浏览器和服务器交换http消息,最后关闭TCP连接。
可以看出,http是基于tcp的。是可靠的,请求相应一一对应。
另外
HTTP协议是无状态协议:无状态指的是客户端发送HTTP请求给服务端之后,服务端根据请求响应数据,响应完后,不会记录任何信息。这种特性有优点也有缺点,缺点是无法共享数据。无状态的,因此无法做连续多个步骤的操作。例如:加入购物出,结算,支付。每次都需要验证身份信息,但是无状态所以无法连续。解决办法就是利用会话技术(Cookie、Session)。优点就是速度快。
HTTPS 协议(Hyper Text Transfer Protocol Secure),是 HTTP 的加强安全版本。HTTPS 是基于 HTTP 的,也是用 TCP 作为底层协议,并额外使用 SSL/TLS 协议用作加密和安全认证。可以理解成HTTPS = HTTP + SSL/TLS。默认端口号是 443。SSL依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信加密。
SSL/TLS的核心要素是非对称加密。非对称加密采用两个密钥——一个公钥,一个私钥。在通信时,私钥仅由解密者保存,公钥由任何一个想与解密者通信的发送者(加密者)所知。
常用的非对称加密算法:RSA。
常见的对称加密算法有:DES、3DES和AES
在实际通信过程中,计算的代价较高,效率太低,因此,SSL/TLS 实际对消息的加密使用的是对称加密。

https的主要步骤:1、客户使用https的URL访问Web服务器,要求与Web服务器建立SSL连接。2、Web服务器收到客户端请求后,会将网站的证书信息(证书中包含公钥)传送一份给客户端/。3、客户端的浏览器与Web服务器开始协商SSL连接的安全等级,也就是信息加密的等级。4、客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话密钥加密,并传送给网站。5、Web服务器利用自己的私钥解密出会话密钥。6、Web服务器利用会话密钥加密与客户端之间的通信。
结合了对称加密和非对称加密的方式。
数字签名实现完整性。数字证书CA实现身份认证。加密实现密文传输。
常见的状态码:
100-199 用于指定客户端应相应的某些动作。
200-299 用于表示请求成功。
300-399 用于已经移动的文件并且常被包含在定位头信息中指定新的地址信息。
400-499 用于指出客户端的错误。
500-599 用于支持服务器错误。

如果服务器收到头信息中带有100-continue的请求,这是指客户端询问是否可以在后续的请求中发送附件。
200 OK:客户端请求成功。
300表示被请求的文档可以在多个地方找到,并将在返回的文档中列出来。如果服务器有首选设置,首选项将会被列于定位响应头信息中。
301 状态是指所请求的文档在别的地方;文档新的URL会在定位响应头信息中给出。浏览器会自动连接到新的URL。
403 Forbidden:指的是服务器端有能力处理该请求,但是拒绝授权访问。404 Not Found:请求资源不存在,比如资源被删除了,或用户输入了错误的URL。
408 (Request Timeout/请求超时)
500 Internal Server Error:服务器发生不可预期的错误,一般是代码的BUG所导致的。500 (SC_INTERNAL_SERVER_ERROR) 是常用的“服务器错误”状态。该状态经常由CGI程序引起
502 (Bad Gateway/错误的网关)

3、get post put delete等区别
这些都是http定义的与服务器进行交互的不同方法。
从数据库角度来说,get相当于查询,从服务器查询相关数据; post是增加服务器的资源;delete是删除资源;put是修改服务器的资源。
还有其余的,head用来查询头部信息,不返回实体信息;trace用来回环诊断,回显服务器收到的请求,因为请求传递过程中会经过防火墙等,trace查看请求中途是否被更改;options允许客户端查看服务器性能;

由于put是幂等的,也就是如果两次请求相同,那么第二次会覆盖第一次,所以put用来更新资源;而post是非幂等的,不会覆盖,所以用来添加资源。

重点是get和post的区别和联系:
1.一个请求数据,一个上传数据;
2、安全性:get因为参数会放在url中,,get请求会保存在浏览器历史,可保存为书签,所以隐私性,安全性较差,post的数据在body中。
3、数据长度:由于get的请求放在url中,虽然http对url长度没有限制,但是服务器了浏览器有限制,一般在1024字节以内。因为长url解析消耗性能太大,并且容易收到恶意构造长url的攻击。post由于数据放在body中,所以没有限制。示例如下:

GET /updateInfo?name=Javanx&age=25 HTTP/1.1
Host: localhostPOST /updateInfo HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded
name=Javanx&age=25

GET 和 POST 只是 HTTP 协议中两种请求方式(异曲同工),而 HTTP 协议是基于 TCP/IP 的应用层协议,无论 GET 还是 POST,用的都是同一个传输层协议,所以在传输上,没有区别。
但如果不按规范来也是可以的,可以在 URL 上写参数,然后方法使用 POST;也可以在 Body 写参数,然后方法使用 GET。当然,这需要服务端支持。
GET 方法参数写法是固定的吗?
在约定中,我们的参数是写在 ? 后面,用 & 分割。
我们知道,解析报文的过程是通过获取 TCP 数据,用正则等工具从数据中获取 Header 和 Body,从而提取参数。
POST 方法比 GET 方法安全?
有人说POST 比 GET 安全,因为数据在地址栏上不可见。

然而,从传输的角度来说,他们都是不安全的,因为 HTTP 在网络上是明文传输的,只要在网络节点上捉包,就能完整地获取数据报文。

要想安全传输,就只有加密,也就是 HTTPS。
POST 方法会产生两个 TCP 数据包?
有些文章中提到,post 会将 header 和 body 分开发送,先发送 header,服务端返回 100 状态码再发送 body。
HTTP 协议中没有明确说明 POST 会产生两个 TCP 数据包,而且实际测试(Chrome)发现,header 和 body 不会分开发送。
所以,header 和 body 分开发送是部分浏览器或框架的请求方法,不属于 post 必然行为。

4、TCP粘包问题
TCP粘包的本质原因是TCP是基于字节流的协议(为了可靠传输,即前后是有顺序的,和效率,每次都要确认序列号,发送读取的次数不一致,有缓冲区的),这说明数据之间是没有边界的,从TCP首部也能看出来,没有数据部分长度的字段。而UDP是不会产生粘包现象的,它发送的是独立的数据报,UDP首部有数据报长度字段,可以知道读取多少,发送读取的次数一致。
表面原因:
1、发送方采用Nagle算法就可能产生粘包:Nagle是拥塞控制算法,当ftp每次敲击一个字符,就会传一个,此时数据只有1字节,但是TCP/ip首部却达到40字节,浪费资源,造成拥塞。所以nagle算法做了两件事:一是延迟发送小数据,等到上一个确认才发送,二是收集多个小分组,在一个确认到来时一起发送。
2、接收方:如果TCP接收数据包到缓存的速度大于应用程序从缓存中读取数据包的速度,多个包就会被缓存,应用程序就有可能读取到多个首尾相接粘到一起的包。

解决方法:对于发送方造成的粘包问题,可以通过关闭Nagle算法来解决,使用TCP_NODELAY选项来关闭算法。
接收方没有办法来处理粘包现象,只能将问题交给应用层来处理,解决问题的关键在于如何给每个数据包添加边界信息,常用的方法有如下几个:首部中应该至少包含数据包的长度,这样接收端在接收到数据后,通过读取包首部的长度字段,便知道每一个数据包的实际长度了;发送端将每个数据包封装为固定长度(不够的可以通过补0填充);可以在数据包之间设置边界,如添加特殊符号。

5、死锁问题
死锁就是,两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。比如很多进程需要以独占方式占用资源,这样进程间互相等待,无限期陷入僵持。
原因有:资源不足、资源分配不当、进程执行顺序不当等。
死锁的四个必要条件,即只有这四个条件成立,才可能发生死锁,不是肯定的。
互斥:一个资源只能同时被一个进程使用;
占有等待:进程资源得不到满足等待时,不释放已有的资源
不可剥夺:进程资源不能被别的进程抢占;
循环等待:每个进程都在等待链中等待下一个进程所持有的资源

死锁解决办法:
死锁防止:破坏四个必要条件之一即可。比如采用静态分配的方式,静态分配的方式是指进程必须在执行之前就申请需要的全部资源,且直至所要的资源全部得到满足后才开始执行。实现简单,但是严重的减低了资源利用率。剥夺调度能够防止死锁,但是只适用于内存和处理器资源。给系统的所有资源编号,规定进程请求所需资源的顺序必须按照资源的编号依次进行。
总结,死锁防止方法能够防止发生死锁,但必然会降低系统并发性,导致低效的资源利用率。

死锁避免:典型的就是银行家算法。本质就是,每次分配的时候,保证系统处于安全状态,如果这次分配导致不安全状态,则不分配。安全状态就是可以找到一个执行序列,满足每个进程对资源的最大需求,顺利完成执行序列。
银行家算法就是有最大需求矩阵,已分配矩阵,还需要矩阵,可用资源矩阵。分配资源时,若分配大于所需要或分配大于可用资源,不分配;若分配后导致进入不安全状态,不分配。

死锁检测:当且仅当资源分配图不可完全简化,就是死锁。
死锁解除:抢占资源、终止进程。

6、浏览器从输入 URL 开始到页面显示内容,中间发生了什么?
1.进行DNS解析。如果有缓存(浏览器,操作系统,本地DNS服务器)直接找到对应的IP地址,否则,会分别向根域名服务器,顶级域名服务器…直到找到对应的,然后本地DNS服务器将这个IP送回发送端。其中客户机和本地DNS服务器之间的是递归查询,本地DNS服务器和其他DNS服务器之间的查询是迭代查询。
2、TCP三次握手建立连接;
3.开始发送 HTTP 请求报文。请求行包含请求方法、URL、协议版本;请求头包含请求的附加信息,由关键字/值对组成(Host,表示主机名,虚拟主机;Connection,HTTP/1.1 增加的,使用 keepalive,即持久连接,一个连接可以发多个请求;User-Agent,请求发出者,兼容性以及定制化需求。)请求体,可以承载多个请求参数的数据
4、如果有数据一切正常(状态码200),当浏览器拿到服务器的数据(html)之后,开始渲染页面同时获取HTML页面中图片、音频、视频、CSS、JS,在这期间获取到JS文件之后,会直接执行JS代码,阻塞浏览器渲染,因为渲染引擎和JS引擎互斥,不能同时工作,所以通常把Script标签放在body标签的底部。渲染过程就是先将HTML转换成dom树,再将CSS样式转换成stylesheet,根据dom树和stylesheet创建布局树,对布局树进行分层,为每个图层生成绘制列表,再将图层分成图块,紧接着光栅化将图块转换成位图,最后合成绘制生成页面。
5/当数据传送完毕,需要断开 tcp 连接,此时发起 tcp 四次挥手

7、进程间通信方式
1.管道:
匿名管道:两个特点:信息单向传输,只能在父子兄弟进程之间使用(因为没有显式的管道文件,只能fork复制父进程的fd)。
例子:ps auxf | grep mysql 这个就是打印出所有进程信息,通过管道送入右边,再获取其中mysql进程。
命名管道FIFO:可以在不相关的进程间传递信息。使用方法:先需要通过mkfifo命令来创建,并且指定管道名字:mkfifo myPipe
echo “hello” > myPipe // 将数据写进管道 cat < myPipe // 读取管道里的数据。可以看出,管道这种通信方式效率低, 不适合进程间频繁地交换数据。当然,它的好处就是简单。

2、消息队列:
A进程要给B进程发送消息,A进程把数据放在对应的消息队列后就可以正常返回了,B进程需要的时候再去读取数据就可以了。效率更高。
消息队列是内核中消息链表,发送消息是消息体,固定大小的存储块,所以克服了字节流效率低的特点。消息队列生命周期内核持续,不是随进程的。
缺点:消息队列通信过程中,存在用户态与内核态之间的数据拷贝开销,因为进程写入数据到内核中的消息队列时,会发生从用户态拷贝数据到内核态的过程,同理 另一进程 读取内核中的消息数据时,会发生从内核态拷贝数据到用户态的过程

3、共享内存
消息队列的读取和写入的过程,都会有发生用户态与内核态之间的消息拷贝过程。那共享内存的方式,就很好的解决了这一问题。
共享内存的机制,就是拿出一块虚拟地址空间来,映射到相同的物理内存中。这样这个进程写入的东西,另外一个进程马上就能看到了,都不需要拷贝来拷贝去,传来传去, 大大提高了进程间通信的速度。
缺点是:多人写的话,会产生覆盖问题,读没问题。

4、信号量(按理说不严格属于进程通信)
为了防止多进程竞争共享资源,而造成的数据错乱,所以需要保护机制,使得共享的资源,在任意时刻只能被一个进程访问。正好,信号量就实现了这一保护机制。信号量其实是一个整型的计数器,主要用于实现进程间的互斥与同步,而不是用于缓存进程间通信的数据。控制信号量的方式有两种原子操作:一个是P操作,这个操作会把信号量减去1,另一个是V操作,这个操作会把信号量加上1。P操作是用在进入共享资源之前,V操作是用在离开共享资源之后,这两个操作是必须成对出现的。初始为0是同步信号量,初始为1是互斥信号量。

5、信号
信号一般用于一些异常情况下的进程间通信,是一种异步通信,它的数据结构一般就是一个数字。信号来源主要是键盘或者命令(比如kill)。crtrl+C就是产生 SIGINT 信号,表示终止该进程;资源管理器结束进程;kill -9 1050,表示给PID为1050的进程发送SIGKILL 信号,用来立即结束该进程

6、socket
socket就是常见的网络编程。跨网络与不同主机上的进程之间通信,就需要Socket通信。

8、程序、进程、线程、协程
进程是程序在某个数据集合上的一次运行活动,也是操作系统进行资源分配和保护的基本单位
所以程序是静态的,进程是动态的,有生命周期的。
进程的组成:PCB(进程描述符,进程控制管理信息比如阻塞挂起等,资源分配信息,CPU寄存器相关信息)、数据段、程序段。
进程三种基本状态:阻塞(等待某一事件,比如IO完成)、运行、就绪(缺少CPU,比如CPU时间用完)

线程:一个进程可以有很多线程,是轻量级的进程,不同的线程共享进程的资源(内存,IO等),没有自己的地址空间,但有自己的堆栈和局部变量。线程是处理器调度的基本单位,而进程是资源分配的基本单位。
比如浏览器是一个进程,其中的HTTP 请求线程、事件响应线程、渲染线程等等,所以线程并发程度比进程高,同时由于创建或撤销进程时,系统都要为之分配或回收资源,如内存空间、I/O 设备等,需要较大的时空开销,而线程相对开销小从属于不同进程的线程间切换,它是会导致进程切换的,所以开销也大

缺点:一个线程崩溃会影响其他线程,所以健壮性不够

协程:协程是一个用户态的轻量级线程。线程是同步的,协程是异步的。
进程线程的痛点是涉及到线程阻塞状态和可运行状态之间的切换,同步锁,上下文切换。比如JDBC,数据库是最大性能瓶颈,因为是同步阻塞的,线程占用的CPU一直在空转。
协程切换:当出现IO阻塞的时候,协程调度切换时,将数据流立刻yield掉(主动让出),将寄存器上下文和栈保存到其它地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,且其他协程可以继续运行,不会使整个线程阻塞住;
第二是可以不加锁的访问全局变量,所以上下文的切换非常快,因为协程都是属于一个线程的,不存在同时写变量冲突。

临界资源:一次仅允许一个进程使用的资源称为临界资源。许多物理设备都属于临界资源,如打印机等。访问临界资源的那段代码称为临界区

9.智能指针问题
智能指针是一个,用来存储指向动态分配对象的指针,负责自动释放动态分配的对象,防止堆内存泄漏。动态分配的资源,交给一个类对象去管理,当类对象声明周期结束时,自动调用析构函数释放资源。
使用new和delete运算符进行动态内存的管理虽然可以提高程序的效率,但是也非常容易出问题:忘记释放内存,造成内存泄漏,在尚有指针引用内存的情况下就将其释放,产生引用非法内存的指针,程序发生异常后进入catch忘记释放内存。智能指针是借用RAII技术对普通指针进行封装。RAII技术,也称为“资源获取就是初始化”,是C++语言的一种管理资源、避免泄漏的惯用法。使用存储在栈上的局部对象(类)来封装资源的分配和初始化,在构造函数中完成资源的分配和初始化,在析构函数中完成资源的清理,可以保证正确的初始化和资源释放。 局部对象是指存储在栈的对象,它的生命周期是由操作系统来管理的,无需人工介入。
C++11版本之后提供的智能指针包含在头文件中,分别是auto_ptr、shared_ptr、unique_ptr、weak_ptr
智能指针代码实现: 用两个类来实现智能指针的功能,一个是引用计数类,另一个则是指针类。

//  引用计数器类  用于存储指向同一对象的指针数
template<typename T>
class Counter
{private://  数据成员T *ptr;    //  对象指针int cnt;   //  引用计数器//  友元类声明template<typename T>friend class SmartPtr;//  成员函数//  构造函数Counter(T *p)   //  p为指向动态分配对象的指针{ptr = p;cnt = 1;}//  析构函数~Counter(){delete ptr;}
};
//  智能指针类
template<typename T>
class SmartPtr
{private://  数据成员Counter<T> *ptr_cnt;  //  public://  成员函数//  普通构造函数  初始化计数类SmartPtr(T *p){ptr_cnt = new Counter<T>(p);}//  拷贝构造函数 计数器加1SmartPtr(const SmartPtr &other){ptr_cnt = other.ptr_cnt;ptr_cnt->cnt++;}//  赋值运算符重载函数SmartPtr &operator=(const SmartPtr &rhs){ptr_cnt = rhs->ptr_cnt;rhs.ptr_cnt->cnt++; 增加右操作数的计数器ptr_cnt->cnt--; 左操作数计数器减1if (ptr_cnt->cnt == 0)delete ptr_cnt;return *this;}//  解引用运算符重载函数T &operator*(){return *(ptr_cnt->cnt);}//  析构函数~SmartPtr(){ptr_cnt->cnt--;if (ptr_cnt->cnt == 0)delete ptr_cnt;elsecout << "还有" << ptr_cnt->cnt << "个指针指向基础对象" << endl;}
};

shared_ptr:采用引用计数器的方法,允许多个智能指针指向同一个对象,每当多一个指针指向该对象时,指向该对象的所有智能指针内部的引用计数加1,每当减少一个智能指针指向对象时,引用计数会减1,当计数为0的时候会自动的释放动态分配的资源。
shared_ptr初始化:


std::shared_ptr<T> sp; //空shared_ptr,可以指向类型为T的对象std::shared_ptr<int> sp(new int(5)); //指定类型,传入指针通过构造函数初始化std::shared_ptr<int> sp = std::make_shared<int>(5); //使用make_shared函数初始化//智能指针是一个模板类,不能将一个原始指针直接赋值给一个智能指针,因为一个是类,一个是指针
std::shared_ptr<int> sp = new int(1); //error

unique_ptr unique_ptr唯一拥有其所指的对象,在同一时刻只能有一个unique_ptr指向给定对象。转移一个unique_ptr将会把所有权全部从源指针转移给目标指针,源指针被置空;所以unique_ptr不支持普通的拷贝和赋值操作,不能用在STL标准容器中;局部变量的返回值除外(因为编译器知道要返回的对象将要被销毁);如果你拷贝一个unique_ptr,那么拷贝结束后,这两个unique_ptr都会指向相同的资源,造成在结束时对同一内存指针多次释放而导致程序崩溃。
初始化:没有make_shared函数,只能通过new传入指针。

std::unique_ptr<T> up; //空unique_ptr,可以指向类型为T的对象,up会使用delete来释放它的指针std::unique_ptr<int> up(new int(5)); //绑定动态对象

nique_ptr没有copy构造函数,不支持普通的拷贝和赋值操作;但却提供了一种移动机制来将指针的所有权从一个unique_ptr转移给另一个unique_ptr(使用std::move函数,也可以调用release或reset)

std::unique_ptr<int> upMove = std::move(up); //转移所有权std::unique_ptr<int> up1(new int(5));
std::unique_ptr<int> up2(up1.release()); //up2被初始化为up1原来保存的指针,且up1置为空
std::unique_ptr<int> up3(new int(6));
up2.reset(up3.release()); //reset释放了up2原来指向的内存,指向up3原来保存的指针,且将up3置为空

unique_ptr适用范围比较广泛,它可返回函数内动态申请资源的所有权;可在容器中保存指针;支持动态数组的管理。

weak_ptr是一种弱引用指针,它是伴随shared_ptr而来的,不具有普通指针的行为 ,模板类中没有重载 * 和 -> 运算符,这也就意味着,weak_ptr 类型指针只能访问所指的堆内存,而无法修改它。。它主要是解决了shared_ptr引用计数的问题:在循环引用时会导致内存泄漏的问题。
weak_ptr指向一个由shared_ptr管理的对象,将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。如果一块内存被shared_ptr和weak_ptr同时引用,当所有shared_ptr析构了之后,不管还有没有weak_ptr引用该内存,内存也会被释放。所以weak_ptr不保证它指向的内存一定是有效的,在使用之前使用函数lock()检查weak_ptr是否为空指针。
use_count() 查看指向和当前 weak_ptr 指针相同的 shared_ptr 指针的数量。
expired() 判断当前 weak_ptr 指针为否过期(指针为空,或者指向的堆内存已经被释放)
lock() 如果当前 weak_ptr 已经过期,则该函数会返回一个空的 shared_ptr 指针;反之,该函数返回一个和当前 weak_ptr 指向相同的 shared_ptr 指针.
循环引用:A调用B,B调用A,这样初始化时A,B的计数为1,赋值时又加1,析构减1,最后还是1,资源没有释放。

智能指针线程安全吗?
结论:同一个shared_ptr被多线程读是安全的;同一个shared_ptr被多线程写不安全;共享引用计数的不同的shared_ptr被多个线程”写“ 是安全的。
原因,shared_ptr其实由指向对象的指针和计数器组成,计数器加减操作是原子操作,所以这部分是线程安全的,但是指向对象的指针不是线程安全的。比如智能指针的赋值拷贝,首先拷贝指向对象的指针,再使引用次数加减操作,虽然引用次数加减是原子操作,但是指针拷贝和引用次数两步操作 并不是原子操作,线程不安全,需要手动加锁解锁。

10. 二叉搜索树、平衡二叉树、红黑树、B树、B+树
二叉搜索树:为了使查找的平均时间复杂度为logn,性质是左子树节点小于根,右子树节点大于根,同时左右子树也是二叉搜索树,是一个递归定义。特点是中序遍历的话是递增序列。
但是,如果本身是一个递增序列,那么构造的二叉搜索树就退化成链表了,查找复杂度变成O(n)了,所以才有平衡二叉搜索树。
AVL的特点是左右子树的高度差不超过1,左右子树也满足。把插入,查找,删除的时间复杂度最好情况和最坏情况都维持在O(logN)。但是频繁旋转会使插入和删除牺牲掉O(logN)左右的时间(为了保持平衡,插入删除元素都要调整二叉树)。
因此,才有了红黑树。
红黑树一些特点:节点是红色或黑色,根节点是黑色;红色节点的孩子是黑色节点;从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。
虽然这么构造深意我也不理解,但是是为了从根到叶子的最长的可能路径不多于最短的可能路径的两倍长。结果是这个树大致上是平衡的,但不是AVL限制那么严格。这么做原因是换来了保证每次插入最多只需要三次旋转就能达到平衡,实现起来也更为简单。AVL调整旋转次数就不可预计了。
红黑树虽然减少了树的高度,但是当数据量很大时,树高度还是很高,不适合io级别的操作,更适合内存级别的应用。比如STL中哈希表unordered_map的底层实现就是红黑树,可以实现查找插入删除的复杂度都是logn级别。

那么,适用于io操作的是B树和B+树,适用于数据库的索引
B树就是一个多路的二叉搜索树,B树每个节点有键、数据、指针三部分。每个节点有m-1个元素和2-m个孩子节点,这样就大大减小树的高度,从而减小io操作次数。
B+树是B树的变种,B+树的非叶子结点只保存指针和键,数据保存在叶子结点。B+树在叶子结点添加了指向相邻叶子结点的指针。B+树由于非叶子节点没有数据域,所以能够携带更多的键,所以B+树的层数少,看起来更矮胖一点。那么查询时,B+树所进行的I/O次数更少;由于B+树在叶子结点增加了指向相邻叶子结点的指针,当进行区间查询时,只要沿着指针读取就可以,天然具备排序功能。而B树的索引字段大小相邻近的结点可能隔得很远。

11.深拷贝和浅拷贝
浅拷贝只是复制了对象的引用地址,两个对象指向同一个内存地址,所以修改其中任意的值,另一个值都会随之变化;深拷贝是将对象及值复制过来,指向两个独立的地方,两个对象修改其中任意的值另一个值不会改变,这就是深拷贝。
进一步思考,在对对象进行浅拷贝时,如果两个对象都析构函数的话,就会导致多次析构造成崩溃。
同时,在传参时,值传递就是深拷贝,比如vector a作为形参,那么函数里的a变化,不会导致函数外面的a变化,就会发现你的a没变化,因为函数退出时,局部的a已经销毁了。而且深拷贝复制对象时还浪费时间空间,开销很大。如果传vector& a,就是浅拷贝了,只复制了地址。

12.友元问题
由于类实现了封装,变量一般是私有的,需要通过成员函数访问。但是有一些函数需要频繁访问数据成员,就需要频繁的使用成员函数调用,效率较低,因为调用成本,类型检查等事项)
所以友元函数是放弃了一些封装性,提高效率,使其可以直接访问类的私有成员。
它是定义在类外的普通函数,它不属于任何类,但需要在类的定义中加以声明,声明时只需在友元的名称前加上关键字friend,放在私有共有都可以。而且一个函数可以是不同类的友元函数,只要在不同类声明就可以。
friend 类型 函数名(形式参数);
看起来像一个特权函数。

友元类: 友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息(包括私有成员和保护成员)。
同样,在类外定义一个类B。然后在类A内声明friend class B;就可以了。B的所有成员函数就可以直接访问A的私有或保护成员了。

注意:友元关系不能被继承。若C继承了B,那么C并不是A的友元类。友元关系是单向的,也不能传递。我想这些限制都是为了最大限度保持封装性,毕竟友元是特殊情况才声明的,权利不能滥用。

13、计算机系统开机的过程
第一阶段:BIOS,基本输入输出系统,控制硬件的一段代码,存放在ROM中,无法更改的,断电不消失。其中主要包含了自检程序、系统自动装载程序、IO驱动程序中断服务等。
1.1 BIOS程序首先检查,计算机硬件能否满足运行的基本条件,这叫做**”硬件自检”;**
1.2 **启动顺序:BIOS知道下一阶段的启动程序”具体存放在哪一个设备

第二阶段:主引导记录
BIOS按照”启动顺序”,把控制权转交给排在第一位的储存设备(U盘,硬盘等),然后读取启动设备的主引导记录,存放在最前面的512字节。它主要包含分区表,它的主要作用是,告诉计算机到硬盘的哪一个位置去找操作系统

第三阶段:**硬盘启动,**计算机的控制权就要转交给硬盘的某个分区

第四阶段,操作系统
控制权转交给操作系统后,操作系统的内核首先被载入内存。以Linux系统为例,内核加载成功后,第一个运行的程序是/sbin/init。它根据配置文件产生init进程。这是Linux启动后的第一个进程,pid进程编号为1,其他进程都是它的后代。
然后,init线程加载系统的各个模块,比如窗口程序和网络程序,直至执行/bin/login程序,跳出登录界面,等待用户输入用户名和密码。

14. cookie,session区别
http是无连接的,这次请求和上次请求没有关系。但是如果需要数据共享,追踪用户行为(购物车)就需要知道用户信息。
cookie是一种存储在浏览器的字段信息,只有4kb,以键值对形式存在。一般访问流程:
用户http请求;服务器在响应头加一个set-cookie选项,里面包含cookie。之后用户再发送http请求时就会把cookie信息加在请求部分里面,服务器就会进行相应的业务响应。
session和cookie看起来很像。但是我们要分清session概念和session实现。session就是一个会话,相当于给服务器和浏览器建立一个连接。那么session的实现就是利用cookie为载体的,服务器会为每个浏览器产生一个独一的session id来标识连接,之后每次请求只要把id放在请求头部就可以知道浏览器是谁了。而一些用户信息上下文信息都是存储在服务器中,请求时只需要复制id就可以。而这个id往往就是通过cookie实现的。也就是说cookie是实现session id传递的载体之一。如果浏览器禁用cookie的话,session id也可以通过url重写实现。
所以综合来说,cookie很具体,就是一种服务器生成,存储在浏览器上的小字段,实现鉴权的具体方式。而session是一种宽泛的会话技术,通过session id标识,为服务器浏览器建立连接。
区别总结:
1、cookie存储在浏览器中,所以安全性较差,容易被劫持伪造;session只有id在浏览器中,具体信息存储在服务器中,安全性好一点,但是会增加服务器的负担,而且多个服务器的话负载均衡后很有可能找不到了。比如自动保存的密码等。
2、cookie只有4kb大小,只能存ASCII字符,而session存储信息不限,类型也很多。

15. 谈一谈http长连接、短连接、超时
明确一个概念,http是无状态的应用层协议,没有长短连接一说,请求响应和下一次没有关系的。这里的长连接实际上是指TCP连接。
短连接就是这一次请求响应结束后,下一次请求响应就要重新建立TCP连接。Connection:close就是短连接
长连接就是TCP连接不关闭,下一次请求响应就不用再三次握手四次挥手了,减少资源消耗,比如一次请求 HTML,可能还需要请求后续的 JS/CSS/图片等。http1.0默认是短连接,1.1默认是长连接。
一般长连接就是在请求头设置:Connection:keep-alive 和Keep-Alive: timeout=60。有timeout说明60s后连接失效,没有的话说明连接一直有效。
对于点对点的,交互频繁的。比如数据库就是长连接。对于web网页这种,用户很多,一般用短连接。不然的话会有成千上万的连接同时保存在服务器端。
长连接还有一个额外的问题,就是队头阻塞。在请求应答过程中,如果出现任何状况,剩下所有的工作都会被阻塞在那次请求应答之后。
解决办法:现代浏览器会针对单个域名开启6个连接,通过各个连接分别发送请求。它实现了某种程度上的并行,但治标不治本。
HTTP/2是完全多路复用的,而非有序并阻塞的。http2在一个连接上处理多个请求,实现流式传输,将请求分片,每个请求都有自己的id标识,到达服务器后再组装起来。这样就实现多路复用,提高效率。

超时的情况:请求超时,比如现在网络超级不好,当客户端发起一个请求,通信层开始请求与服务器建立连接(包括在重试),如果在5S之内还没有连接到服务器,那么认为超时。
响应超时一个不正确的url,将会响应404。或者服务器响应速度太慢,连接已经关闭。

  1. Linux系统的目录结构及目录的主要功能
    我们可以用ls /命令来查看linux的目录。ls就是显示目录下的文件名。/就是根目录,显示根目录下的文件,目录也是文件。

bin: cd bin;ls就可以看到bin目录下的文件。普通用户可以使用的必须的命令的存放目录。比如ls,pwd等等。是二进制文件。
sbin:超级root用户可以使用的系统管理的必须的命令的存放目录。普通用户无法执行。普通用户用$标识,root用#标识。
boot: 引导程序,内核等存放的目录。
dev :是 Device 的缩写, 该目录下存放的是 Linux 的外部设备,在 Linux 中访问设备的方式和访问文件的方式是相同的。设备文件可以使用mknod命令来创建。想要Linux系统支持某个设备,只要:相应的硬件设备,支持硬件的驱动模块,以及相应的设备文件。
/home:用户的主目录,在 Linux 中,每个用户都有一个自己的目录,一般该目录名是以用户的账号命名的,保存了用户自己的配置文件,定制文件,文档,数据等。
/lost+found:看名字就知道是系统崩溃非法关机等文恢复的位置。一般是空的。
/mnt:系统提供该目录是为了让用户临时挂载别的文件系统的,我们可以将光驱挂载在 /mnt/ 上,然后进入该目录就可以查看光驱里的内容了。
/proc: 是 Processes(进程) 的缩写,/proc 是一种伪文件系统,存储的是当前内核运行状态的一系列特殊文件,这个目录是一个虚拟的目录,它是系统内存的映射,我们可以通过直接访问这个目录来获取系统信息
这个目录的内容不在硬盘上而是在内存里,我们也可以直接修改里面的某些文件,比如可以通过下面的命令来屏蔽主机的ping命令,使别人无法ping你的机器。
/tmp:tmp 是 temporary(临时) 的缩写这个目录是用来存放一些临时文件的。实际上是内存中的,当关机重启后tmp清空了。
/var: 是 variable(变量) 的缩写,这个目录中存放着在不断扩充着的东西,我们习惯将那些经常被修改的目录放在这个目录下。包括各种日志文件、缓冲文件等。
/etc: 是 Etcetera(等等) 的缩写,这个目录用来存放所有的系统管理所需要的配置文件。例如,要配置系统开机的时候启动那些程序,配置某个程序启动的时候显示什么样的风格等等。通常这些配置文件都集中存放在/etc目录中,所以想要配置什么东西的话,可以在/etc下面寻找我们可能需要修改的文件。
/lib:lib 是 Library(库) 的缩写这个目录里存放着系统最基本的动态连接共享库,其作用类似于 Windows 里的 DLL 文件(system32目录)。几乎所有的应用程序都需要用到这些共享库。按理说,这里存放的文件应该是/bin目录下程序所需要的库文件的存放地。
/media:linux 系统会自动识别一些设备,例如U盘、光驱等等,当识别后,Linux 会把识别的设备挂载到这个目录下。比如插入U盘会在里面建一个disk目录,就能通过disk来访问u盘。
/opt:opt 是 optional(可选) 的缩写,这是给主机额外安装软件所摆放的目录。比如你安装一个ORACLE数据库则就可以放到这个目录下。默认是空的。
/usr这个目录中包含了命令库文件和在通常操作中不会修改的文件。这个目录对于系统来说也是一个非常重要的目录,其地位类似Windows上面的”Program Files”目录
/usr/local这个目录存放的内容,一般都是我们后来自己安装的软件的默认路径
/usr/bin一般存放的只是对用户和系统来说“不是必需的”程序(二进制文件)。
/usr/sbin一般存放用于系统管理的系统管理的不是必需的程序(二进制文件)。

16. XSS攻击是什么?如何避免?
XSS攻击全称跨站脚本攻击(前端注入),注入攻击的本质,是把用户输入的数据当做前端代码执行(比如SQL注入)
。XSS拼接的是网页的HTML代码,一般而言我们是可以拼接出合适的HTML代码去执行恶意的JS语句。在渲染DOM树的时候,执行了不可预期的JS脚本,从而发生了安全问题。(信息泄露、未授权操作、弹窗关不掉等)
常见的 XSS 攻击有三种:反射型XSS攻击、DOM-based 型XXS攻击以及存储型XSS攻击。
反射型 XSS 一般是攻击者通过特定手法(如电子邮件),诱使用户去访问一个包含恶意代码的 URL,当受害者点击这些专门设计的链接的时候,恶意代码会直接在受害者主机上的浏览器执行。反射型XSS通常出现在网站的搜索栏、用户登录口等地方,常用来窃取客户端 Cookies 或进行钓鱼欺骗
例子:张三做了一个超链接发给阿伟,超链接地址为:http://www.xxx.com?content= 当阿伟点击这个链接的时候(假设他已经登录xxx.com),浏览器就会直接打开bbb.com,并且把xxx.com中的cookie信息发送到bbb.com。而bbb.com就是张三的非法网站,此时他已经得到了cookie信息。

存储型XSS也叫持久型XSS,主要将XSS代码提交存储在服务器端(数据库,内存,文件系统等),下次请求目标页面时不用再提交XSS代码。当目标用户访问该页面获取数据时,XSS代码会从服务器解析之后加载出来,返回到浏览器做正常的HTML和JS解析执行,XSS攻击就发生了。存储型 XSS 一般出现在网站留言、评论、博客日志等交互处,恶意脚本存储到客户端或者服务端的数据库中。
例子:张三在网站发布了文章,其中包含恶意代码:。
这样,只要你打开文章,就会丢失cookie信息,危害更大。

基于 DOM 的 XSS 攻击是指通过恶意脚本修改页面的 DOM 结构,是纯粹发生前端的攻击。属于前端 JavaScript 自身的安全漏洞。常见于类似JSON转换、翻译等工具区。

防御:1.对用户向服务器提交的信息(URL、关键字、HTTP头、POST数据等)进行检查,仅接受规定长度、适当格式、预期内容,其余的一律过滤
2.对输入内容的特定字符进行编码,例如表示 html标记的 < > 等符号。
3. 对重要的 cookie设置 httpOnly, 防止客户端通过document.cookie读取 cookie.
4. 确定接收到的内容被规范化,仅包含最小最安全的tag(不含JavaScript),去掉对任何远程内容的引用(尤其是样式表和JavaScript)

17.Cmake怎么用?为什么要用?
为什么要CMAKE工具呢?
我们如果直接把可执行代码给别人运行,可能由于平台不一样无法运行,怎么办呢?就要用make工具,实际上make工具有很多种,而生成的makefile文件形式也千差万别,所以,CMAKE出现,允许开发者编写一种平台无关的 CMakeList.txt 文件来定制整个编译流程,然后再根据目标用户的平台进一步生成所需的本地化 Makefile 和工程文件。所以编译流程是先写 CMakeList.txt ,再cmake 路径生成makefile文件,再make一下生成可执行文件、动态库静态库等文件。实现写一次就可以运行在任何系统上。
CMakeList.txt 主要内容有

cmake_minimum_required(VERSION 3.0)  //最小版本
project(sylar) //工程名字set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_CXX_FLAGS "$ENV{CXXFLAGS} -rdynamic -O3 -fPIC -ggdb -std=c++11 -Wall -Wno-deprecated -Werror -Wno-unused-function -Wno-builtin-macro-redefined -Wno-deprecated-declarations") #C++标准。比如-fPIC代表生成动态库,-O3优化级别,-ggdb可以用gdb调试set(LIB_SRCsylar/log.cc) # 设置要编译的源文件add_library(sylar SHARED ${LIB_SRC})  #编译成动态库 把log源文件编译成动态库,这样就可以给test的main函数用
#add_library(sylar_static STATIC ${LIB_SRC})
#SET_TARGET_PROPERTIES (sylar_static PROPERTIES OUTPUT_NAME "sylar")add_executable(test tests/test.cc)  #编译成可执行文件,将test源文件编译成可执行文件
add_dependencies(test sylar)SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) #设置可执行文件的存储路径,一般就在bin目录下
SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib) #设置动态库文件的存储路径,一般在lib文件下

总结一下,就是设置要编译的源文件、要生成的动态库静态库,可执行文件,设置生成文件的存储位置等。

计算机基础面经积累---持续更新相关推荐

  1. mysql参数积累 持续更新。。。

    mysql参数积累 持续更新... 以下是Mysql数据库服务器配置文件my.ini的详细配置.应用场合是InnoDB引擎,2核CPU, 32位SUSE. [client] #password = y ...

  2. 程序员常用英语积累---持续更新

    程序员常用英语积累---持续更新: Distribution: 分发 Direction    : 方向 Description: 描述 Destination: 目标 Definition   : ...

  3. javaSE基础重点知识点总结 持续更新

    javaSE基础重点知识点解析 文章目录 javaSE基础重点知识点解析 前言 1.重载和重写 2.匿名对象 3.可变个数形参的方法 4.MVC设计模式 5.java.lang.Object类 6.自 ...

  4. 计算机考研资料库!近五十所高校计算机考研资料分享!持续更新中!

    由于文章内无法添加百度云链接,所以领取方式可以看这里 计算机考研资料库目录!(1) 计算机考研资料库目录!(2) 以下是考研资料库内已有资料,更多资料持续更新中,如果你需要哪个学校的计算机相关专业真题 ...

  5. 【计算机英语词汇和词组-持续更新中】

    推荐词典:有道词典 理由:在看外文网站的时候,可以实现 取词和划词翻译 这是 在看外文网站的时候,一点点 记录的学习笔记,归纳后方便记忆 按照 首字母顺序排列 备注的发音音标,都是美式的发音 持续更新 ...

  6. 计算机优质书籍搜集(持续更新)

    目录 计算机基础 计算机网络 操作系统 数据结构 算法 数据库 数据库基础 MySQL Redis Java Java基础 并发 JVM Spring/SpringBoot 面试 计算机基础 计算机网 ...

  7. 计算机相关书籍推荐(持续更新)

    学计算机也有几年了,眼看明年就要毕业,在这里总结一下我看过的书,并推荐一些我认为好的书,还有一些是我听说好的但没看过的,也写在这里,对于下面的书,如果看过的我会按自己的读后感打一个分和一些评价,评分及 ...

  8. 国家开放大学本科计算机基础机考2020,(2021更新)最新国家开放大学电大本科《计算机应用基础》网络课网考形考作业一及二试题答案.docx...

    (2021更新)最新国家开放大学电大本科<计算机应用基础>网络课网考形考作业一及二试题答案.docx 最新国家开放大学电大本科计算机应用基础网络课网考形考作业一及二试题答案 盗传必究 形考 ...

  9. 计算机考研题目汇总【持续更新】

    第一题:-6 解析 信号量的当前值如果是正值N,该值表示有N个可用资源. 如果为0,则表示所有资源全部被分配,同时没有进程处于等待状态 如果为负数N,则表示全部资源分配完毕,且还有N个进程处于等待该资 ...

最新文章

  1. 基于TF-IDF编码进行文本聚类分析:文档成对相似性计算、层次聚类(链接矩阵、树形图dendrogram绘制、聚类标签)
  2. 初学Netty(杰哥好久不见)
  3. Boost:使用静态c ++内核语言扩展以进行编译和 执行模板化的c ++内核
  4. mysql将时间轴转化为时间_MySQL日期计算及格式转换有关问题
  5. Mysql数据库 自动增长 重新从0开始
  6. Postman 把response的值自动放到变量里
  7. 全网首发:FreeType加载字体图像的几个关键函数
  8. ie支持html5代码,使用 HTML5 Shiv 让 IE 支持 HTML5
  9. 一文图解自定义修改el-table样式
  10. 在Mac和PC之间共享鼠标键盘(拥有多台电脑者必看)
  11. TOC和TOB产品的区别是什么
  12. Color Models (RGB, CMY, HSI)
  13. 互联网络业的十大发展趋势
  14. 企业如何实现全员网络营销 上海添力网络营销
  15. 捷联惯导速度更新_划桨效应补偿算法推导(双子样)
  16. .NET开发资料 dotnet 学习的站点
  17. 新闻发布管理系统/新闻网站
  18. Tesseract-Ocr图片内容识别
  19. php许愿墙mysql_许愿墙的搭建基于mysql
  20. 使用PLAN法提升执行力——笔记与答案

热门文章

  1. SpringBoot第 5 讲:SpringBoot+properties配置文件读取
  2. 回流焊接温度曲线用户手册 (HLW)
  3. 《数字中国建设整体布局规划》充分发挥“数据”生产要素:形成横向打通、纵向贯通、协调有力的一体化推进格局...
  4. slice、splice、split 三者的区别
  5. 2022年全国大学生数学建模竞赛E题思路
  6. 简单超声波报警器的实现(arduino+超声波传感器+蜂鸣器+LED)
  7. 批处理(bat)语法
  8. 【转】中国行政区域(县区级带坐标经纬度)
  9. rhino软件上Grasshopper 中的快捷键(用gh的同学不妨了解一下)
  10. 加拿大大学 计算机专业排名2015,加拿大大学计算机专业排名一览