JeffHung.Blog

(My smile insists of having nose. :-)

Detecting VC6 service pack version

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 [...]

Race condition in C wrapper of mutex class

本系列共有三篇文章,以及一篇補充資料,建議依照以下順序閱讀:

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 [...]

Implementing dprintf() with __VA_ARGS__

在程式寫作的過程中,通常我們會需要輸出一些訊息,方便我們瞭解程式的運作情形,以便偵錯。因為這些訊息,對程式的真正使用者,也就是我們開發者的客戶,並沒有意義。是故,通常我們會將程式分成測試版 (debug version 或 debug mode) 或釋出版 (release version 或 release mode),然後只在測試版裡輸出這些訊息,而在釋出版裡完全抑制這些訊息的輸出。本文介紹如何實作完美的 dprintf() 來傾印偵錯訊息。

Overloading C++ conditional operator for mixing types

有時候,在搭配 conditional operator (?:) 輸出資料時,我們會依據資料的值,來決定輸出什麼東西。例如:

#include <iostream>

using namespace ::std;

int main()
{
int delay_time = -1; // negative for "random" delay time.

cout << "delay: ";
if (delay_time < 0) {
cout << "random";
}
else [...]

ISO C++ conformant _read()? XD

因為在 porting 某支程式,所以用 MSDN 找 read(),想要確定該 include 哪個 header,link 哪個 library,結果 MSDN 的 read() 頁面,僅僅顯示這麼一行:

This POSIX function is deprecated beginning in Visual C++ 2005. Use the ISO C++ conformant _read instead.

這真是活見鬼了,什麼時候 ISO C++ 裡有以底線開頭的 API 了?更別提 _read() 根本不是 ISO C++/POSIX 的 function。
好吧,他說的是 conformant,所以不是在說 _read() 是 ISO C++ 的標準,而是說用 _read() 的方法呼叫 read(),才符合 ISO C++ 的一些規定。但即使如此,這個解釋,還是怎麼聽來就怎麼怪。
勉強為其解釋,我記得 Microsoft 平台有一種 [...]

不求甚解 2

第一集《不求甚解》還在撰寫中[1],今天又上演第二集了。
某人宣稱,若用 C# 寫 COM 包 C 寫的 library,因為 C# 有記憶體管理機制,記憶體會自動 free,所以就可以不用呼叫 C library 提供的 uninit() 了喔。
最好是這樣啦,這回我不跟你玩了,出問題不要怪我沒提醒過。
老毛病,寫著寫著,就會想要把技術細節寫清楚,以便以後自己可以查閱,都忘了文章的主要目的了。 ↩

文章被抄.啼笑皆非

剛剛發現,我的這篇《Detect & post-build for Intel C++ Compiler》,被一個中國人全文抄錄到他的 blog 裡。由於整個排版,仍然是原來的樣子,甚至連裡面的 footnotes,連結也都是連回到我的 blog,因此可以合理推斷,是被直接「複製/貼上」全文抄錄的。
被全文抄錄不打緊,因為反正我用的授權模式是 CC:by,也就是只要有明確標示出,原作者是我,即可全文抄錄,任意使用。事實上,被抄其實是我的榮幸。
不過,在看到對方甚至連「轉載自」的字樣都沒寫[1],卻剛好得以符合 CC:by 的規定的原因是,因為直接使用「複製/貼上」,所以連文章標題下面那一小塊,標示分類、作者以及發表日期的區塊,也一併複製,因而恰好符合了,須標示原作者的條件。這不禁讓我感到,啼笑皆非。

2007-09-05 更新:又被另一個中國人無視著作權規定地全文抄錄。這次他忘記把「posted by」這段也抄到,所以明確地違反了 CC:by。
2007-09-06 更新:Kenneth 已經加上來源說明了。

2007-09-26 更新:
再兩例:《練習寫 TracMacro - [[TicketStatus]]》與《Implementing dprintf() with __VA_ARGS__》。一樣因為是直接「複製/貼上」全文抄錄,含作者資訊,所以符合 CC:by。該 blog 許多文章看起來也都是「複製/貼上」來的,其他的來源,不一定允許這種全文抄錄,就看那些被抄的作者,決定怎麼反應了。
又,訪客留在我的 blog 的留言,也被抄錄了。理論上我站上的訪客留言並沒有做任何版權宣告,故應被視作是 copyright reserved,這部份因為也被抄錄了,所以請敝站也被抄襲的訪客留言作者,自行向該 blog 聲討囉[2]。

要到對方 blog 的首頁,才會發現「本空间文章,未经原作者同意,请勿做商业用途。未注明的文章均为转载。」的字樣。又,就算對方有註明「未经原作者同意,请勿做商业用途」,但該篇文章「真正的原作者」其實是我,而我用 CC:by,允許商業使用。所以有需要的人,請隨意,不必理會抄錄者的授權宣告。 ↩我不擁有訪客留言的智慧財產權,故無法代為聲討。 ↩

回應 tfing 的問題

tfing 在我這篇《新同事》詢問,為甚麼我遇到的一些情況,是不好的。寫一寫發現太多了,乾脆另開一篇。
在 VC6 裡,做 .lib 時,是不會檢查 dependency 的。也就是說,如果你呼叫了另外一個 .lib 的 function,只有 compiler 會檢查該 function 有否宣告過,linker 不會檢查該 symbol 是否存在。因此,如果 include path 有設,header 也有 #include,就不會顯示任何錯誤。必須要等到用該 .lib 的人,在做 .exe 或 .dll 時,才會產生 missing symbol 的錯誤。[1]
另外,.lib 相當於是把所有 function 都赤裸裸地開放出來,這樣就沒有所謂的「模組介面」,因此很容易就會亂呼叫 function,而沒有注意到,呼叫了不應有相依關係的 component 裡的函式[2]。又由於前述不會有 missing symbol 錯誤的關係,而無法察覺這樣的錯誤,因而導致最終程式的 dependency 關係會一團亂。
亂 call function,除了上面「呼叫了不應有相依關係的 component 裡的函式」的狀況之外,還包含了「喜歡自行在 .c/.cpp 檔前面,重複宣告函式,而不是用 #include 將對應的 header 引入」。 這會造成當所依存的 component 更新,prototype 改變時,會無法於 [...]

dsw2dot.pl - extract and draw project dependencies

很多時候,build 程式時最後會死在 link error,一堆 symbol 會找不到。最後追查下來,通常會發現是 project dependencies 沒有設好的緣故。由於是「找不到」而不是「用得不對」,因此我們通常得用 grep 之類的工具,從十幾萬行的程式裡,去尋找遺失的 symbol 在哪裡。當一個 dependency 忘記設時,可能遺失的 symbols 會達上百個[1],要一個一個手動尋找時,就很討厭了。
為了避免這樣的情形,也為了方便確認目前系統各 components 的關聯情形,如同原本預計的理想狀態,我寫了一個簡單的 script,叫 dsw2dot.pl,能夠 parse VC6 的 dsw 檔,然後依據內函的各 project 檔的相依情形,產生 GraphViz 的 dot 檔 script。這樣一來,我就可以用 dot 產生 png/svg/... 等各種圖形了。
這個程式的 usage 如下:
Usage: dsw2dot.pl [ <option> ... ] <dsw-file> [ <dot-file> ]

Generate graphviz digraph script <dot-file> according to project dependenciesthat [...]

Detect & post-build for Intel C++ Compiler

Intel C++ Compiler (ICC) 所編譯出來的執行檔,其速度總令人驚豔,且可以近乎無痛地與 Microsoft Visual C++ (MSVC) 的開發經驗整合,是升級開發工具的好選擇。然而,在 Windows 上,ICC 需要搭配隨 ICC 附上的 libmmd.dll,才能夠執行,再加上 ICC 和 MSVC 是可以隨時切換的,因此,在 build system 的設計上,必須要有些特別的設計,以便處理這種 IDE 不會處理到的事。
我們用的 MSVC 是 VC6,需要偵測目前使用的編譯器,是 MSVC 還是 ICC,如果是 ICC 的話,還要偵測是哪一個版本,然後,依據偵測到的版本,作對應的 post-build 的動作。例如,若是使用 ICC 的話,就將正確版本的 libmmd.dll,複製到目標目錄下。
以下假設 ICC 是安裝在 ICPP_COMPILER 這個目錄下,如 %ProgramFiles%\Intel\Compiler\C++\9.1。
裝了 ICC 後,compiler/linker 會被換成在 %ICPP_COMPILER%\..\..\ISELECT\bin\ 目錄下的 xicl6.exe 跟 xilink6.exe,這只是一個只是一個 front-end,ICC 會依據目前的設定,啟動對應的 compiler/linker 進行編譯或連結。
依據隨附 [...]

 Prev 1 2 3 4 5 6 Next