巧妙使用static 為資料打包並傳送

2021-07-04 20:04:04 字數 3123 閱讀 6581

只要做過專案的朋友對關鍵字static應該都有一些了解,但未見了解很全面的。在c語言中,關鍵字static有以下明顯的作用:1.static變數分配到靜態記憶體中,這一點和全域性非靜態變數相同。

2.在函式體,static變數只要不進行修改操作,在被呼叫過程中其值將保持不變。

3.在模組內,全域性static變數可以被模組內所有函式訪問,但不能被模組外其它函式訪問。它是乙個本地的全域性變數,具有私有特點。

4.在模組內,乙個static函式只可被這一模組內的其它函式呼叫。那就是,這個函式被限制在宣告它的模組的本地範圍內使用,也具有私有特點。

如果我們能夠很好地利用static的這些特性,書寫高內聚低耦合,更具模組化的**就不會顯得象句口號;如果不能很好地理解和使用它,一切都只是空談。下面來舉個例子來說明static在實際應用可能會遇到問題。

<------packet----->

| header | data |

我想有人可能會這麼做:

#define max_packet_size 1600

typedef struct _header

header;

boolsend(bool type,uint8*data,uint32 length)

;/*定義陣列*/

header* pheader=(header*)packet;

if(null==data || length<1)

/*設定包頭*/

pheader->type=type;

pheader->length=length;

pheader++;

memcpy((uint8*)pheader,data,length);/*拷貝資料到包頭之後*/

netsend(packet);/*將包傳送到網路*/

return true;

}對於上面的**,有人可能會有這樣的疑慮,傳送資料報到網路是乙個非常頻繁的操作,所以在send函式中,頻繁地為packet分配棧記憶體是一種低效的做法。他可能會將上的**修改為:

boolsend(bool type,uint8*data,uint32 length)

packet= (uint8*)malloc(length+sizeof(header));

if(null==packet)

pheader=(header*)packet;

pheader->type=type;

pheader->length=length;

pheader++;

memcpy((uint8*)pheader,data,length);

net_send(packet);/*將包傳送到網路*/

free(packet);

packet=null;

return true;

}使用動態記憶體好象可以解決上面的問題,但它沒有考慮到頻繁地使用malloc-free會產生大量的記憶體碎片。在嵌入式系統環境中,一般記憶體大小有限,所以這種做法最終會導致分配失敗。對於處理大流量資料問題,一種比較常用的高效方法就是在函式內部使用靜態陣列(全域性靜態陣列在這個應用中不建議使用,因為全域性變數會增加函式間的耦合度)。嘿嘿,聽到這樣的建議,估計有人會馬上這麼改:

boolsend(bool type,uint8*data,uint32 length)

;header* pheader=(header*)packet;

if(null==data || length<1)

pheader->type=type;

pheader->length=length;

pheader++;

memcpy((uint8*)pheader,data,length);

net_send(packet);/*將包傳送到網路*/

memset(packet,0,sizeof(packet));/*清除本次記憶體操作*/

return true;

}朋友且慢,小心地雷!

你是否忘了考慮**可重入(reentrance)問題呢?這裡使用packet靜態陣列的確不用頻繁地分配動態或棧記憶體,但同時引入了**不可重入的問題。因為函式內的static變數分配在靜態記憶體區,供所有物件共用。在多工系統中,如果有乙個以上的任務同時訪問該記憶體,很可能會出現問題。所以我們必須要用其它手段來消除這個不可重入問題。使用訊號量semaphore是乙個很好解決不可重入問題的方法。在上面**中加入訊號量:

boolsend(bool type,uint8*data,uint32 length)

;header* pheader=(header*)packet;

if(null==data || length<1)

semtake(semaphore,wait_forever);/*等待訊號量*/

pheader->type=type;

pheader->length=length;

pheader++;

memcpy((uint8*)pheader,data,length);

net_send(packet);/*將包傳送到網路*/

memset(packet,0,sizeof(packet));/*清除本次記憶體操作*/

semgive(semaphore);/*釋放訊號量*/

return true;

}踩過這個地雷,修改這個bug也化了很大功夫

使用idea打包web專案為war

前言 idea匯出war包的方式與myeclipse有一點不同,使筆者在使用的時候有點困惑,在網上查閱相關資料的時候,發現其描述十分不清晰,於是就有了這篇隨筆的誕生。話不多說,直接進入正題。注 idea版本14.1.7 注 1.修改war包的名稱 根據實際情況 2.如果出現web inf資料夾則刪除...

使用py2exe打包MySQLdb程式為exe

最近寫了乙個日誌管理的指令碼localloghousekeeper.py,是在ubuntu下寫的。考慮測試python script的跨平台性,老大要求打包為exe程式,然後測試執行在沒有安裝python,沒安裝任何第三方外掛程式的windows xp上。下面是整個流程的乙個總結 1 在window...

Gson打包混淆後返回的資料為null

使用 override public void onnext responsestringresponse 錯誤資訊 分析 解決辦法 直接編譯的時候沒有問題,當我打包好測試的時候發現返回的資料居然為null 這塊是我gosn的混淆 gson keep class sun.misc.unsafe ke...