被乙個巨集折騰了2次,才偶然發現問題。問題挺隱蔽的,也許是自己對bug出現後的表現,還不太敏感。
以前認為巨集需要大寫,可能就是看著舒服,維護方便。
經過這個bug後,增加了體會。巨集大寫可以降低除錯的難度,提高**的清晰度。
最近維護的linux工程,為了出win版。**中不可避免的用巨集隔開,或定義了一些在win和linux下都能用的巨集。
在工程中使用了, pthreads-w32庫。
封裝了乙個簡單的socket類, 對socket基本操作,進行了封裝。
當socket任務完成時,需要關閉socket控制代碼。
linux版沒問題。
在win版下,呼叫closesocket(h_sock), 直接報錯了,陷在_close裡面。
當時就想不明白,windows下關閉乙個socket控制代碼不就是要呼叫closesocket麼?還能咋樣?
因為不關socket控制代碼,在頻繁操作(e.g. 封裝了乙個函式,裡面連線伺服器,傳送資料,關閉控制代碼)的情況下,記憶體不到乙個小時,就被吃的差不多了。
既然不能呼叫closesocket,我就理所當然的認為,一定是被pthreads-w32坑了。
當時用closehandle來代替closesocket,測試的時間不長,沒有記憶體洩漏了,暫時先這樣。
這是乙個月之前的事情。
前天,發現執行這個demo的計算機,長時間執行以後,再開socket服務,已經不行了,bind失敗。這時候知道了,用closehandle來代替closesocket的後果,產生了控制代碼洩漏。當頻繁呼叫那個封裝函式時(e.g. 發乙個小檔案,就呼叫一次封裝函式)。當執行幾個小時後,socket控制代碼就被用的差不多了。
下面就是必須要解決這個問題,究竟咋的了。
知道呼叫closesocket會崩潰,那就單步進去崩著看。
當崩潰的時候,落在_close裡面。當時感到好無助:( 這closesocket引數就乙個socket控制代碼,呼叫一下就完事了,還能怎樣?
突然想到,這不是乙個api麼?為啥會陷在原始碼裡面?迷惑啊。
回到closesocket的呼叫點,不是有原始碼麼? 那f12一下。
f12到位後,被驚呆了。看到**是乙個巨集。。。
#define closesocket(sk) close(sk)
這使我深深的體會到,巨集為什麼要大寫。
最近才開始正式維護這個工程,我不太確定這個可愛的巨集是不是我寫的。去查svn可以確定作者,但是該工程從舊版公升級上來,有幾個svn, 查起來不方便。這個巨集就是我寫的,又咋的了:)
問了老同事,他說這個巨集以前就有。
因為這個工程以前是linux版,估計原作者也是為了以後這個類能相容win版,就定義了這個迷惑性很強的巨集。但是這個巨集在這個socket封裝類中並沒有使用。因為關閉控制代碼時,直接呼叫close(sk)就可以。這個巨集就埋在這裡了。
其實這個巨集可以寫成下面這樣, 讓非原作者不要入坑太深。當包含了適當的標頭檔案後,不進該坑。
#ifndef closesocket
#define closesocket(sk) close(sk)
#endif // #ifndef closesocket
如果用大寫來表示巨集,就很明了,使用者絕對不會入坑, 一看到就知道是巨集。
巨集的名稱也不要和api的名稱相同。
#ifndef safe_close_socket
#ifndef win32
#define safe_close_socket(sk) \
if (invalid_socket != (sk))
#else
#define safe_close_socket(sk) \
if (invalid_socket != (sk))
#endif
#endif // #ifndef safe_close_socket
一定要用遞迴嗎?!
2017 02 14 今天看資料結構的時候,自己考慮了一下,如何用程式來實現這個函式。結果我的想法是利用迴圈的方式,而書上使用的方式是利用遞迴,所以就查了查這部分的內容,對比了下迴圈和遞迴的優缺點。首先,最重要的一點,就是這段函式的 盡量不使用遞迴。但是有時候,可能不使用遞迴,就會導致 量急劇上公升...
一定要用的 requestBody註解
後端接受前端傳遞的引數相信我們都用過 httpservletrequest的getparameter方法,但是在獲取資料方面都是key,value的方式,像十幾個傳遞的引數可能要在後台寫很多get,set方法來獲取或儲存獲取到的資料,就像這樣 而我們將資料定義在訊息體內,通過requestbody的...
vue中data為啥一定要用函式???
知道這個是為啥,咱們可以模擬深拷貝和淺拷貝的原理。淺拷貝 將原物件或原陣列的引用直接賦給新物件 新陣列,新物件 陣列只是原物件的乙個引用,新的物件陣列改變原來物件陣列也隨之改變。深拷貝 兩個物件之間沒有任何關係 建立乙個新的物件和陣列,將原物件的各項屬性的 值 陣列的所有元素 拷貝過來,是 值 而不...