小黑盒和长亭科技面经

首先是小黑盒的电话面试

Q:浅拷贝构造与深拷贝构造

类中有指针的时候,需要用深拷贝开辟一块新内存

Q:什么是SQL注入,怎么解决SQL注入

什么是SQL注入?

SQL注入(SQLi)是一种注入攻击,,可以执行恶意SQL语句。它通过将任意SQL代码插入数据库查询,使攻击者能够完全控制Web应用程序后面的数据库服务器。攻击者可以使用SQL注入漏洞绕过应用程序安全措施;可以绕过网页或Web应用程序的身份验证和授权,并检索整个SQL数据库的内容;还可以使用SQL注入来添加,修改和删除数据库中的记录。

SQL注入漏洞可能会影响使用SQL数据库(如MySQL,Oracle,SQL Server或其他)的任何网站或Web应用程序。犯罪分子可能会利用它来未经授权访问用户的敏感数据:客户信息,个人数据,商业机密,知识产权等。SQL注入攻击是最古老,最流行,最危险的Web应用程序漏洞之一。

SQL注入攻击的类型

SQL注入攻击可以通过多种方式执行。在选择特定攻击方法之前,攻击者可能会观察系统的行为。

带内注入

这是典型的攻击,攻击者可以通过相同的通信通道发起攻击并获得结果。这是通过两种带内技术完成的:

● 基于错误的SQL注入:从显示的错误消息中获取有关数据库的信息

● 基于联合的SQL注入:依赖于攻击者能够将UNION ALL被盗信息的结果与合法结果连接起来。

这两种技术都依赖于攻击者修改应用程序发送的SQL,以及浏览器中显示的错误和返回的信息。如果应用程序开发人员或数据库开发人员无法正确地参数化他们在查询中使用的值,那么它会成功。两者都是试错法,可以检测到错误。

盲注入

也称为推理SQL注入,盲注入攻击不会直接从目标数据库中显示数据;相反,攻击者会仔细检查行为中的间接线索。HTTP响应中的详细信息,某些用户输入的空白网页以及数据库响应某些用户输入需要多长时间,这些都可以是线索,具体取决于攻击者的目标。他们还可以指向攻击者尝试的另一个SQLi攻击途径。

带外注入

这种攻击有点复杂,当攻击者无法在单个直接查询 - 响应攻击中实现其目标时,攻击者可能会使用此攻击。通常,攻击者会制作SQL语句,这些语句在呈现给数据库时会触发数据库系统创建与攻击者控制的外部服务器的连接。以这种方式,攻击者可以收集数据或可能控制数据库的行为。

二阶注入就是一种带外注入攻击。在这种情况下,攻击者将提供SQL注入,该注入将由数据库系统的单独行为存储和执行。当二级系统行为发生时(它可能类似于基于时间的作业或由其他典型管理员或用户使用数据库触发的某些事情)并且执行攻击者的SQL注入,那就是当“伸出”到系统时攻击者控制发生了。

如何防止SQL注入攻击?

以下建议可以帮助防止SQL注入攻击成功:

不要使用动态SQL

避免将用户提供的输入直接放入SQL语句中;最好使用准备好的语句和参数化查询,这样更安全。

不要将敏感数据保留在纯文本中

加密存储在数据库中的私有/机密数据;这样可以提供了另一级保护,以防攻击者成功地排出敏感数据。

限制数据库权限和特权

将数据库用户的功能设置为最低要求;这将限制攻击者在设法获取访问权限时可以执行的操作。

避免直接向用户显示数据库错误

攻击者可以使用这些错误消息来获取有关数据库的信息。

对访问数据库的Web应用程序使用Web应用程序防火墙(WAF)

这为面向Web的应用程序提供了保护,它可以帮助识别SQL注入尝试;根据设置,它还可以帮助防止SQL注入尝试到达应用程序(以及数据库)。

定期测试与数据库交互的Web应用程序

这样做可以帮助捕获可能允许SQL注入的新错误或回归。

将数据库更新为最新的可用修补程序

这可以防止攻击者利用旧版本中存在的已知弱点/错误。

总结:SQL注入是一种流行的攻击攻击方法,但是通过采取适当的预防措施,例如确保数据加密,保护和测试Web应用程序,以及您是最新的补丁程序,您可以采取有意义的步骤来保持您的数据安全。

Q:从输入一个URL到访问到资源经历的过程

应用层:http

传输层:tcp

网络层:ip

数据链路层:arp

物理层:比特流

Q:URL转ip地址用的什么协议?该协议传输层用的什么协议?为什么?

DNS协议。

DNS系统采用递归查询请求的方式来响应用户的查询,其一般过程如下:

(1)客户端首先向首选域名服务器查询。

(2)首选域名服务器检查本地资源记录,如果存在则作权威回答,如果不存在,则检查本地缓存,如果有记录则直接返回结果。若本地资源记录和缓存记录都不存在,则向根域名服务器查询。

(3)根域名服务器返回相应顶级域的权威域名服务器的地址,首选域名服务器继续向该顶级权威域名服务器查询。

(4)顶级权威域名服务器返回次级域的权威域名服务器地址,首选域名服务器如此迭代查询,直到得到对查询域名的权威回答,保存在本地缓存中并返回给客户端,完成此次查询。目前绝大多数的网络都会开放DNS服务,DNS数据包不会被防火墙等网络安全防护设备拦截,因此,可以基于DNS协议建立隐蔽通道,从而顺利穿过防火墙,在客户端和服务器之间隐蔽地传输数据。

DNS区域传输的时候使用TCP协议:

1.辅域名服务器会定时(一般3小时)向主域名服务器进行查询以便了解数据是否有变动。如有变动,会执行一次区域传送,进行数据同步。区域传送使用TCP而不是UDP,因为数据同步传送的数据量比一个请求应答的数据量要多得多。

2.TCP是一种可靠连接,保证了数据的准确性。

域名解析时使用UDP协议:

客户端向DNS服务器查询域名,一般返回的内容都不超过512字节,用UDP传输即可。不用经过三次握手,这样DNS服务器负载更低,响应更快。理论上说,客户端也可以指定向DNS服务器查询时用TCP,但事实上,很多DNS服务器进行配置的时候,仅支持UDP查询包。

Q:什么是索引,为什么要使用索引,索引使用多了会造成什么后果?

索引是对数据库表中一个或多个列的值进行排序的结构。

设置索引付出的代价:1:增加了数据库的存储空间 2:插入和修改的时候需要花费较多的时间(因为索引也要随之变动)

好处:提高了表的搜索效率

Q:TCP为什么是3次握手?

3次握手可以实现功能,4次的话比较多余,如果是2次握手的话会出现问题,具体问题如下解释:

A发一个消息给B,网络原因阻塞,然后A超时重传。当A和B通信完了之后,这个阻塞的消息到达了B,B以为是A的一个新请求,所以一直会给他一个确认,等待和A建立连接发数据,但是对于A来言,他不会去理睬这个确认,所以B的资源就被浪费了。

Q:什么是逻辑地址,什么是物理地址,页面置换算法有哪些?

逻辑地址(Logical Address) 是指由程序产生的与段相关的偏移地址部分。

物理地址就是内存中真实的地址

页面置换算法有:FIFO,OPT,LRU,NRU

Q:线程/进程之间通信方法?死锁怎么预防?使用多线程需要注意哪些问题?

进程间通信:

管道,命名管道,信号量,消息队列,信号,共享内存,套接字,全双工管道

线程间通信:

锁机制,信号量机制,信号机制

Q:递归转迭代需要用什么数据结构?为什么?

用栈,递归本来就是函数栈的调用

Q:服务端80端口被占用怎么办?

netstat可以查看端口状态

Q:什么命令可以查看进程运行状态?

ps命令

准备长亭科技视频面试的时候的YY

Q:topK问题

1.排序,取第k大,时间复杂度O(nlogn)

2.使用堆,复杂度O(nlogk)

3.冒泡,复杂度O(k*n)

4.BFPRT算法,复杂度O(n)

Q:写一个快排

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 1e6+100;
int n;
int a[MAX_N];

#define dbg(x) cout << #x"=" << x << endl;

int partition(int *a, int l, int r){
int key = a[l];
while(l < r){
while(l < r && key <= a[r]) --r;
a[l] = a[r];
while(l < r && a[l] <= key) ++l;
a[r] = a[l];
}
a[l] = key;
return l;
}

void quickSort(int *a, int l, int r){
int p; // 中间的位置
if(l < r){
p = partition(a, l, r);
quickSort(a, l, p-1);
quickSort(a, p+1, r);
}
}

int main(){
//freopen("in.txt", "r", stdin);
cin >> n;
for(int i = 0; i < n; ++i) cin >> a[i];
quickSort(a, 0, n-1);
for(int i = 0; i < n; ++i){
cout << a[i] << " ";
}
cout << endl;
return 0;
}

Q:写一个0/1背包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <bits/stdc++.h>
using namespace std;
int T;
const int MAX_N = 1e3+100;
int N,V; // N:个物品 V:容量
int v[MAX_N], w[MAX_N]; // v:价值, w:重量
int f[MAX_N];

int main(){
//freopen("in.txt", "r", stdin);
ios::sync_with_stdio(0); cin.tie(0);
cin >> T;
while(T--){
cin >> N >> V;
for(int i = 0; i <= V; ++i) f[i] = 0;
for(int i = 0; i < N; ++i){
cin >> v[i];
}
for(int i = 0; i < N; ++i){
cin >> w[i];
}
for(int i = 0; i < N; ++i){
for(int j = V; j >= w[i]; --j){
f[j] = max(f[j], f[j-w[i]]+v[i]);
}
}
cout << f[V] << endl;
}
return 0;
}

面完长亭科技之后记得的问题,以为凉了但是还是得实习offer了

Q:死锁的必要条件

互斥条件

请求与保持条件

不剥夺条件

循环等待条件

Q:写三路快排

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 1e6+100;
int n;
int a[MAX_N];

#define dbg(x) cout << #x"=" << x << endl;

/*
[l, lt-1] < v
[gt, r] > v
[lt, gt-1] = v

x x x x x x x x x x

*/
void partition(int *a, int l, int r, int &lt, int &gt){
int key = a[l];
lt = l;
gt = r + 1;
int i = l+1;
while( i < gt ){
if(a[i] < key){
swap(a[i++], a[lt+1]); lt++;
} else if(a[i] > key){
swap(a[i], a[gt-1]); gt--;
} else i++;
}
swap(a[l] , a[lt]);
}

void quickSort(int *a, int l, int r){
int lt, gt;
if(l < r){
partition(a, l, r, lt, gt);
quickSort(a, l, lt-1);
quickSort(a, gt, r);
}
}

int main(){
freopen("in.txt", "r", stdin);
cin >> n;
for(int i = 0; i < n; ++i) cin >> a[i];
quickSort(a, 0, n-1);
for(int i = 0; i < n; ++i){
cout << a[i] << " ";
}
cout << endl;
return 0;
}

Q:写LCA(二叉树就行)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(root == NULL || root == p || root == q) return root;
TreeNode* left = lowestCommonAncestor(root->left, p, q);
TreeNode* right = lowestCommonAncestor(root->right, p, q);
if(left != NULL && right != NULL) return root;
else if(left != NULL) return left;
else if(right != NULL) return right;
else return NULL;
}
};

Q:红黑树的定义

面试得offer了就没看,坑待填

Q:正则表达式是什么文法

面试得offer了就没看,坑待填

emm.坚持原创技术分享,您的支持将鼓励我这个小菜鸡的创作!