巨集一定要用大寫

2021-08-10 05:52:39 字數 1944 閱讀 6769

被乙個巨集折騰了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為啥一定要用函式???

知道這個是為啥,咱們可以模擬深拷貝和淺拷貝的原理。淺拷貝 將原物件或原陣列的引用直接賦給新物件 新陣列,新物件 陣列只是原物件的乙個引用,新的物件陣列改變原來物件陣列也隨之改變。深拷貝 兩個物件之間沒有任何關係 建立乙個新的物件和陣列,將原物件的各項屬性的 值 陣列的所有元素 拷貝過來,是 值 而不...