本系列共有三篇文章,以及一篇補充資料,建議依照以下順序閱讀:
Race condition in C wrapper of mutex class (補充資料)
Implementing dprintf() with __VA_ARGS__
Implementing dprintf() without __VA_ARGS__
Implementing DFORMAT and DOUT (尚未完成)
在這篇《Implementing dprintf() with __VA_ARGS__》裡,簡介了如何利用 __VA_ARGS__ 做出好用的 dprintf(),以協助我們僅在測試版裡傾印偵錯訊息。然而,某些老舊但仍然十分活躍的 compilers,如 VC6,並沒有支援 __VA_ARGS__。因為通常來說,為了照顧既有的大量程式,以及一些政治問題,更換 compiler 有時是不可能的。所以我們最好還是來想想,怎樣在不支援 __VA_ARGS__ 的情況下,仍然將 dprintf() 實作出來。
仔細檢視 dprintf_v2() 與 dprintf_v3() 在 #define 時的差別,我們會發現,dprintf_v2() 其實並不是一個真正的 function-like macro,而僅僅只是把 dprintf_v2 這個「名字」給代換成 dprintf_v2_impl。於是,原本跟在後面,屬於 dprintf_v2 的參數,經過 preprocessor 處理之後,變成了跟在 dprintf_v2_impl 的後面。這樣的作法,除了之前提過的,在釋出版裡,剩下來的參數列,不一定有辦法被最佳化去掉之外,還有一個更大的問題就是,沒有辦法於呼叫 dprintf_v2() 時省略 __FILE__ [...]
(這是一篇積存的舊文,原始發想時間大約在 2007 年,但精確的日子已不可考。)
這是怎樣,平均每個月可以遇到一個 VC6 的問題,真苦。XD
這次的問題出在 strftime() 這個標準 C 的函式。依據 C99,若傳進 strftime() 的 format specifier 有 %Z 或 %z 的話,分別應該被代換為:
%Z is replaced by the locale’s time zone name or abbreviation, or by no characters if no time zone is determinable. [tm_isdst]
%z is replaced by the offset from UTC in the ISO8601 format ‘‘-0430’’ (meaning 4 hours [...]
Microsoft Visual C++ 6 (VC6) 是個歷史悠久的 compiler,自 1998 年推出之後,一直到了 2002 年,才有 Visual Studio .NET 2002 這個後繼版本推出。在這期間,Microsoft 一共推出了 6 個 service packs,以解決各種 VC6 的 bug。但在實務上,我們並沒有一個很方便的方法,可以得知目前灌在系統裡的 VC6,其 service pack 的版本為何:
從 VC6 選單的 Help > About Visual C++,我們只會看到簡單的「Visual C++R 6.0」的版本號。
從控制台的「變更或移除程式」,我們也只能看到「Microsoft Visual Studio 6.0 xxx Edition」的字樣。
能否弄清楚 patch 到那一版的 service pack,有時候非常重要。不同的 service pack 版本,小則編譯出來的程式執行效率不同,大則執行結果不同,這些差異,無法忽視。
根據 MSDN 的這篇《How To Tell That a [...]
(這是一篇自 2005 年開始撰寫[1],最近才補完的舊文,文中的連結可能已經失效,請見諒。)
在 moztw 看到這篇《你喜歡甚麼等距字型?》,在討論寫程式時,用什麼等距字型比較好。因為我很討厭 moztw 必須要註冊才能發表文章的政策,但這又是蠻有趣的議題,因此拉回來自己討論自己的。
在這篇《Finding the Best Programmer's Font》裡,n8f8 列出了他認為,寫程式用的字型,應該具備以下條件:
Crisp clear characters. (清晰)
Extended character-set. (延伸字元集)
Good use of whitespace. (妥善使用空白字元)
'l', '1' and 'i' are easily distinguished. (能夠清楚分辨大寫 l、數字 1 以及小寫 i).
'0', 'o' and 'O' are easily distinguished. (能夠清楚分辨數字 0、小寫 o 以及大寫 O).
Forward quotes from back quotes are easily distinguished -prefer mirrored appearance. (能夠清楚分辨 forward [...]
看到 Neo 在介紹 Wamap (挖地圖),想到還沒試過 Google Map 的中文門牌查詢,就試了一下,發現了驚人的笑果:
查「民族路30-9號」跑出「民族路16-9號」[1];
查「民族路30-9號14樓之3」跑出「民族路29巷3弄9號」。
感覺像是前端文字處理就爛掉了的樣子。
只看第一筆查詢,還可以解釋說是因為圖資不夠,所以演算法自動找「從地址來看最接近的地點」來顯示。但搭配第二筆查詢來看,很明顯就是前端文字處理爛掉了,樓層高度對這種地圖門牌查詢來說,並無意義,本來就應該先濾掉。但很明顯地,整個被攪和進去,結果跟第一筆的結果不同。
台廠有 UrMap 可以用,門牌查詢還蠻準的,雖然說路徑規劃太多結果,大部分都很莫名其妙,但也都至少有一、兩個是有用的。剛剛 h 君也推薦[2]了 Yahoo! 奇摩生活+地圖,試用了一下也很不錯。
我隱藏了完整測試地址,文中的地址片段也不是與我有關的地址。有興趣的人,可以拿自己家地址試試。 ↩利益揭露:h 君與 Yahoo! TW 有工作往來關係。 ↩
(這是一篇積存的舊文,文中的連結可能已經失效,請見諒。)
從這篇《Comment On Extra Sensitive Case Insensitivity》的 comments 裡,看到一段有趣的程式:
下面這段 Java 並非永遠回傳 true。
"mail".toUpperCase().equals("MAIL")
因為,在土耳其,"i" 的大寫不是 "I"。
不過因為我不懂土耳其文,所以無法驗證這個說法的正確性。
(這是一篇積存的舊文。)
Sudo 是個很好用的工具,讓我們可以盡可能地減少擁有 root 權限的時間,並隱藏 root 密碼,以提升系統安全性[1]。不過,當我們在使用 shell script,而 script 裡只有一小部分需要用到 root 權限時,卻通常是直接用 sudo 或 su 成 root 執行整個 script,讓 script 裡面大部分沒有需要 root 權限的地方,也獲得了 root 權限。如果,我們能夠善用 sudo,只在 script 裡真正需要 root 權限的地方,才切換成 root 身份執行,這樣應該可以降低 script 其他部分,對系統可能的危害。
最簡單的想法,就是在 script 裡,有需要 root 權限的指令前面,加上 sudo 就好了。由於 sudo 會記錄上一次執行的 time-stamp,因此就算我們加上 sudo 的指令,在一個跑上千次的迴圈裡面,我們也只需要輸入密碼一次。好比說:
#!/bin/sh
# backup all configuration files in /etc.
for i in /etc/*; do
[...]
我可不可以不要寫這種 code?
#define NUM 5
int main()
{
FooParam param;
memset(¶m, 0, sizeof(param));
param.size = sizeof(param);
param.num = NUM;
param.results = (FooResult**)malloc(NUM * sizeof(FooResult*));;
FooResult* results_body = (FooResult*)malloc(NUM * sizeof(FooResult));
for (int i = 0; i < [...]
本系列共有三篇文章,以及一篇補充資料,建議依照以下順序閱讀:
Race condition in C wrapper of mutex class (補充資料)
Implementing dprintf() with __VA_ARGS__
Implementing dprintf() without __VA_ARGS__
Implementing DFORMAT and DOUT (尚未完成)
最近[1]在寫 code 時發現了一個隱藏的 race condition,是因為 API 的 prototype 設計錯誤,造成 client code[2] 幾乎無可避免地會寫出 race condition 的程式。
原本的 API 設計
我們有套用 C++ 寫的 thread library,用起來很像 Boost.Thread[3],不過因為我們有許多 C code 也需要用到 thread 的功能,因此這個用 C++ 寫的 thread library,也有提供 C 的 API。
C++ 版 mutex 當然依照 RAII [...]
很久以前就想要好好地重整一下我的 blog 了,剛好趁著搬家重灌系統的機會,好好地整理一番。那時的目標有
真正的版本控制
資料庫瘦身
升級後台編輯用的 FCKeditor
與 Sidebar Widget 相容
IE 下的畫面極為慘烈
其中,「升級後台編輯用的 FCKeditor」已經在《Wordpress 編輯器升級到 FCKeditor 2.5.x》時搞定,theme 的問題暫時先不解決,所以剩下「真正的版本控制」與「資料庫瘦身」兩個目標。
真正的版本控制
以前的作法是,用 Subversion 管理我的 Wordpress 目錄,不過只是簡單的直接 checkout 出 Wordpress 程式。雖然升級或更換版本很方便,svn update 或 svn switch 一下即可,不過自己在 local 端,因應自己的喜好而做的更改,就沒辦法有好的版本控制機制,加以管理了。
也就是說,我希望在能夠隨時將 Wordpress 主網站的更新同步回來之外,還能夠保有自己因喜好而產生的一些小改變。如果 Wordpress 主程式和我自己的改變,是存放在同一個 subversion repository 裡,那這一切就可以做到。
簡單講就是,如上圖,我希望能夠隨時 incrementally 從 Wordpress 主 subversion repository 將最新的修正,mirror 到自己電腦上的 subversion repository 裡,成為一條 mirror branch。然後,又能夠有自己的一條 local branch,儲存自己的喜好,同時又能夠隨時視需要,將 mirror branch 裡的東西,merge 進我的 local [...]