一友人做游戲服務(wù)器,涉及通信模塊和業(yè)務(wù)模塊,在軟件行業(yè)也算個(gè)老兵了,也搞c++n多年了,對(duì)于軟件開發(fā)也有自己的一些想法和心得,將其代碼與我分享,讓我觀贊一下。
c++是我從業(yè)一來一直信奉的開發(fā)工具,雖然近些年一直用python來搞定應(yīng)用需求,但關(guān)鍵時(shí)刻還必須是c++搞定, 所以c++的程序代碼能hold住的。
我知道寫通信部分代碼的關(guān)鍵點(diǎn)在哪里,比如: 性能、安全、完整性、模塊化設(shè)計(jì)和處理,所以有針對(duì)性的去檢查友人的代碼,當(dāng)看到這個(gè)函數(shù)的時(shí)候,致命的錯(cuò)誤來了:
分別在于: 第 13,20行 ,其分別會(huì)導(dǎo)致服務(wù)器崩潰和不響應(yīng)
1
2 tagPack* CClient::getRecvPack()
3 {
4 uv_mutex_lock(&_lockrecv);
5 tagPack *t = NULL;
6 if(_recvPackLenght < 4)
7 {
8 _recvOver = true;
9 uv_mutex_unlock(&_lockrecv);
10 return t;
11 }
12 tagPack* tmp = _lsRecvBuf.front();
13 unsigned int size = *(unsigned int*)&tmp->pack[0];
14 if(_recvPackLenght < size)
15 {
16 _recvOver = true;
17 uv_mutex_unlock(&_lockrecv);
18 return t;
19 }
20 BYTE* mem = new BYTE[size];
21
22 unsigned int index = 0;
23 unsigned int needSize = size;
24 while(true)
25 {
26 if(tmp->size < needSize)
27 {
28 memcpy(&mem[index], tmp->pack, tmp->size);
29 needSize -= tmp->size;
30 index += tmp->size;
31 delete tmp;
32 _lsRecvBuf.pop_front();
33 }
34 else if(tmp->size == needSize)
35 {
36 memcpy(&mem[index], tmp->pack, tmp->size);
37 needSize -= tmp->size;
38 index += tmp->size;
39 delete tmp;
40 _lsRecvBuf.pop_front();
41 }
42 else
43 {
44 memcpy(&mem[index], tmp->pack, needSize);
45 memcpy(tmp->pack, &tmp->pack[needSize], tmp->size - needSize);
46 tmp->size -= needSize;
47
48 needSize = 0;
49 }
50
51 if( needSize == 0 )
52 {
53 t = new tagPack(size);
54 t->addBytes(mem, size);
55 t->_sock = _sock;
56 delete []mem;
57 _recvPackLenght -= t->size;
58 break;
59 }
60 tmp = _lsRecvBuf.front();
61 }
62 uv_mutex_unlock(&_lockrecv);
63
64 return t;
65 }
13行: 開發(fā)者直接將緩存內(nèi)存地址作為接收和發(fā)送地址,沒考慮 字節(jié)序問題 (htonl,ntohl)
20行: 邏輯不嚴(yán)密,如果用戶發(fā)送4個(gè)字節(jié)數(shù)據(jù),且均為0 ,結(jié)果就是服務(wù)器崩潰。
所以codereview還是很重要的,特別是將c++應(yīng)用在性能,效率關(guān)鍵部位的代碼。