1.web安全措施
web服务一些主要的安全防护措施:
-
两层物理隔离 外网——内网,业务层——数据层
-
安装必要的杀毒软件
-
启用IP白名单,仅允许白名单的IP主机访问
-
使用Https进行通信,使用tls加密,而不是直接使用http
-
登录授权,生成唯一的session id /token进行后续操作、接口访问
-
敏感数据进行加密或编码
-
系统软件启用License授权,随时检测授权是否过期,而不是开启软件才检测
-
系统软件进行代码保护,启用加密或加壳防止软件被反编译
——单片机里面的烧录的程序,推荐启用加密,或者启用读保护,防止程序被不法人员使用 -
KMS(Key management system)
引入密钥管理系统 纯软件的密钥管理系统/软硬件结合的密钥管理系统 -
End to end security communication
采用端对端加密通信,中间所有节点只负责透传,不保存任何通信信息 -
启用对称加密/非对称加密进行通信
https://blog.csdn.net/u012842630/article/details/89857386
2.安全验证措施有哪些
略
3.如何应对反爬
- 设置get请求中的User-Agent和Referer字段
User-Agent是检查用户所用客户端的种类和版本。Referer是检查此请求由哪里来,通常可以做图片的盗链判断。 - 控制资源爬取速度,尽量避免触发网站反爬
- 使用IP代理池,每次运行时随机挑选一个做访问IP
网站常常会针对IP访问频率统计,设置一个阈值,当超过这个阈值时,网站就会判断这个IP访问太过频繁,会短时间甚至永久性地禁止该IP地址的访问 。
4.单元测试
gtest的大致使用方法:
为每个待测试类分别创建测试文件,并在该文件实现单元测试代码
创建包含main函数的文件,从此处运行所有的单元测试
编译链接运行即可
在具体编写测试代码时:
TEST函数的第一个参数为测试套件名称,第二个参数为测试套件内的测试用例名称,都是用户自定义
gtest会依据测试套件名称对测试结果分组,所以如果是关联的测试,应该把它们的第一个参数设置为相同。
不同的测试套件可以有相同的测试用例名称
https://blog.csdn.net/guotianqing/article/details/104055221
5.建筑学院项目
略
6.移动语义,以及STL哪些不允许移动?
复制构造:
在对象被复制后临时对象和复制构造的对象各自占有不同的同样大小的堆内存,就是一个副本。
移动构造:
就是让这个临时对象它原本控制的内存的空间转移给构造出来的对象,这样就相当于把它移动过去了,转移了所有权。
复制构造和移动构造的差别:
这种情况下,我们觉得这个临时对象完成了复制构造后,就不需要它了,我们就没有必要去首先产生一个副本,然后析构这个临时对象,这样费两遍事,又占用内存空间,干脆将临时对象原本的堆内存直接转给构造的对象就行了。 当临时对象在被复制后,就不再被利用了。我们完全可以把临时对象的资源直接移动,这样就避免了多余的复制构造。
什么时候该触发移动构造呢?
如果临时对象即将消亡,并且它里面的资源是需要被再利用的,这个时候我们就可以触发移动构造。
std::move
std::move函数可以以非常简单的方式将左值转换为右值引用。
通过std::move,可以避免不必要的拷贝操作。
https://blog.csdn.net/shenhang_/article/details/105713347
C ++ 11“不可移动”类型
例如,std :: mutex没有移动构造函数。
主要是因为我不认为他们应该移动。在一些操作系统中,互斥体可能被建模为句柄(所以你可以复制它们),但是IIRC一个线程互斥体被原地操作。如果你要重新定位,任何线程安全正在飞出窗口(其他线程如何知道互斥体刚刚改变了它的内存地址…)
http://www.voidcn.com/article/p-bvggejgl-bsu.html
7.C++程序加速
1. C++程序运行很慢如何查找原因?
性能分析工具gprof:
gprof是GNU profile工具,可以运行于linux、AIX、Sun等操作系统进行C、C++、Pascal、Fortran程序的性能分析,用于程序的性能优化以及程序瓶颈问题的查找和解决。
通过分析应用程序运行时产生的“flat profile”,可以得到每个函数的调用次数,每个函数消耗的处理器时间,也可以得到函数的“调用关系图”,包括函数调用的层次关系,每个函数调用花费了多少时间。
直观办法:通过写Log的方式在几个重要的节点加上Log并记录时间开是哪快代码段执行的时间长。
一般的原因可能是:
a. 增删改的大众化程序, 慢在 I/O 的多
b. 数据获取次数太多, 获取没用的数据太多.
c. 有CPU密集型的操作.
2. C++程序加速的措施有哪些?
(1) 编译优化
-O1 提供基础级别的优化
-O2提供更加高级的代码优化,会占用更长的编译时间
-O3提供最高级的代码优化
-DNDEBUG 使用标志符控制输出等级
举例:调试版本正常输出log,发布版本不执行log输出
1 #include "glog/logging.h"
2 #include "show.h"
#define NDEBUFG
3 int main(int argc, char **argv)
4 {
5 FLAGS_stderrthreshold = 2;
6 google::InitGoogleLogging(argv[0]); // 初始化GLog库
7 DLOG(ERROR) << "There is error !!!";
8 show();
9 return 0;
10 }
(2) 代码优化
1,C++里面STL自带的vector存取效率不高,在可能的情况下用指针数组代替会大幅提高性能。
2,C++中对象的传递,尽可能使用引用,避免无意义的对象拷贝过程。
3,编译的时候加上 -O3, -DNDEBUG 这两个参数优化选项,可以提高编译出来的程序运行速度。
4,针对多核心的处理器,可以加上openMP,进行多线程处理。尤其对于循环的加速效果很明显!
openmp是由一系列#paragma指令组成,这些指令控制如何多线程的执行程序。另外,即使编译器不支持omp,程序也也能够正常运行,只是程序不会多线程并行运行。
C++程序加速的12个方法
1.将反复使用的数据存放在全局变量里面。
2.使用多线程
3.用a++和++a,a–,--a
4.减少除法运算
从数学上将,CPU中的ALU在算术上只干了两件事,加法,移位,顶多加上取反,在逻辑上,只有与或非异或。
乘法规则,按照被乘数的低位到高位依次计算,如果第n位不为0,那么乘数就左移n位,如果第n为为0 ,那么这步运算结果记为0,最后将每一步的结果相加就是最终的计算结果。
除法规则,按照除数的高位到低位的数字依次和被除数进行比对,如果大于等于被除数,则此步结果记为1,并求得余数,如果小于被除数则将上一步的余数左移一步加上一位的数字再次比较,以此类推,最终将依次计算的结果相连组成二进制就是商,最后一次的余数就是求余的结果。
5.尽量减少值传递,多用引用来传递参数。
6.循环引发的讨论1(循环内定义,还是循环外定义对象)
7.循环引发的讨论2(避免过大的循环)
8.局部变量VS静态变量
9.避免使用多重继承
10.将小粒度函数声明为内联函数(inline)
11.多用直接初始化
12.尽量少使用dynamic_cast
https://blog.csdn.net/xz1308579340/article/details/84330166/
C++ for(auto x : str) 和 for(auto &x : str)的区别:
for(auto x : str)是利用x生成str中每一个值的复制,对x的赋值不会影响到原容器。
for(auto &x : str)是利用x生成str中每一个值的引用,对x的操作会影响到原容器。
C++类的直接初始化和复制初始化
(1)对于一般的内建类型,这两种初始化基本上没有区别。
int a(5);//直接初始化
int a=5;//复制初始化
int a=int (5);//直接初始化
(2)当用于类类型对象时,初始化的复制形式和直接形式有所不同:
直接初始化直接调用与实参匹配的构造函数,复制初始化总是调用复制构造函数。
复制初始化首先使用指定构造函数创建一个临时对象,然后使用复制构造函数将那个临时对象复制到正在创建的对象。
8.golang协程与线程区别
进程:拥有自己独立的堆和栈,既不共享堆,也不共享栈,进程由操作系统调度;
线程:拥有自己独立的栈和共享的堆,共享堆,不共享栈,标准线程由操作系统调度;
协程:拥有自己独立的栈和共享的堆,共享堆,不共享栈,协程由程序员在协程的代码里显式调度
一般来说,协程就像轻量级的线程。
线程一般有固定的栈,有一个固定的大小。而goroutines为了避免资源浪费(亦或是资源缺乏),采用动态扩张收缩的策略:初始量为2k,最大可以扩张到1G。
每个线程都有一个id,在线程创建的时候就会被返回,所以我们可以通过线程的id来操纵线程。但是在golang中没有这个概念,因此我们在编码之初就要考虑协程的创建和释放问题。
线程和 goroutine 切换调度开销方面
线程/goroutine 切换开销方面,goroutine 远比线程小
线程:涉及模式切换(从用户态切换到内核态)、16个寄存器、PC、SP…等寄存器的刷新等。
因为协程在用户态由协程调度器完成,不需要陷入内核,这代价就小了。
所以goroutine:只有三个寄存器的值修改 - PC / SP / DX.
9.python3的string、char[]、bytes区别?
python 3中最重要的新特性可能就是将文本(text)和二进制数据做了更清晰的区分。文本总是用unicode进行编码,以str类型表示;而二进制数据以bytes类型表示。
在python3中,不能以任何隐式方式将str和bytes类型二者混合使用。不可以将str和bytes类型进行拼接,不能在str中搜索bytes数据(反之亦然),也不能将str作为参数传入需要bytes类型参数的函数(反之亦然)。
string可以被编码(encode)成字bytes,bytes也可以解码(decode)成string
字符串转数组
str = '1,2,3'
arr = str.split(',')
print a # ['1','2','3']
数组转字符串
#方法1
arr = ['a','b']
str1 = ','.join(arr)
print str1 # a,b
#方法2
arr = [1,2,3]
str2 = ','.join(str(i) for i in arr)
print str2 # 1,2,3
10.golang的string、char[]、slice、bytes区别
- golang 底层设计中,string 和 slice 的数据类型都是 struct。
- 在 golang 中,string 的实质是只读的切片,内容一旦被定义就不能修改。
- [] byte 字符串数组可以被修改及更新。
- 因为string的指针指向的内容是不可以更改的,所以每更改一次字符串,就得重新分配一次内存,之前分配空间的还得由gc回收,这是导致string操作低效的根本原因。
slice结构:
type slice struct {
array unsafe.Pointer
len int
cap int
}
string的定义如下:
type stringStruct struct {
str unsafe.Pointer
len int
}
切片与数组的区别
切片的数据结构中,包含一个指向数组的指针 array ,当前长度 len ,以及最大容量 cap 。在使用 make([]int, len) 创建切片时,实际上还有第三个可选参数 cap ,也即 make([]int, len, cap) 。在不声明 cap 的情况下,默认 cap=len 。当切片长度没有超过容量时,对切片新增数据,不会改变 array 指针的值。
当对切片进行 append 操作,导致长度超出容量时,就会创建新的数组,这会导致和原有切片的分离。
切片扩容规则
当需要的容量超过原切片容量的两倍时,会使用需要的容量作为新容量。
当原切片长度小于1024时,新切片的容量会直接翻倍。而当原切片的容量大于等于1024时,会反复地增加25%,直到新容量超过所需要的容量。
https://www.cnblogs.com/wt645631686/p/12198154.html
https://studygolang.com/articles/21396
11.mmap文件映射比read快原因
访问文件,这涉及到用户态到内核态的转换。
read():
读取硬盘文件中的对应数据,内核会采用预读的方式,比如我们需要访问100字节,内核实际会将按照4KB(内存页的大小)存储在page cache中将read中需要的数据,从page cache中拷贝到用户缓冲区中。整个过程涉及到用户内核态的切换,还有就是数据拷贝。
mmap():
mmap系统调用是将硬盘文件映射到用内存中,说的底层一些是将page cache中的页直接映射到用户进程地址空间中,从而进程可以直接访问自身地址空间的虚拟地址来访问page cache中的页,这样会并未涉及page cache到用户缓冲区之间的拷。
mmap系统调用与read/write调用的区别在于:
mmap只需要一次系统调用,后续操作不需要系统调用。
访问的数据不需要在page cache和用户缓冲区之间拷贝。
https://blog.csdn.net/wuguinianjing/article/details/111049193