這段時間在做一個CS模式的項目,服務端運行在linux/windows平台下,使用C語言;客戶端運行在windows下,使用MFC開發;開發工具為VC++6.0企業版。。
在開發服務端時,由於是使用C語言,所以經常使用malloc,free等C語言函數;在開發起初階段,由於只是開發基礎模塊和基本的功能組件,所以不牽涉到多線程的開發。
在開發過程中,團隊的每個成員都就自己的模塊編寫測試用例,測試用例主要是讓模塊的功能流程跑一遍並確保正常。
前期基本框架搭好之後,後面主要就功能業務進行開發,其中肯定要使用到多線程技術。。。在每個線程中肯定會調用malloc 和free等函數;
開發一個模塊之後,如果可以聯調的話,團隊成員即配合進行聯合調試。。在調試的過程,有時會出現malloc異常和free異常問題。。。。。
針對malloc異常,一直找不到原因,針對free異常,如果是重復釋放等原因,會導致異常。。。
因此後來又寫了一個內存監測模塊,可以輸出內存申請的地址,大小,文件名和行號等信息,同時也可以看出內存釋放的信息,並且就內存申請和內存釋放進行關聯,從而可以查看出內存的情況等。。
但是針對malloc異常情況,一直找不到原因,因為以前是做C++開發的,基本上沒用到過malloc函數,也不知道malloc會異常等。。後來就去網上查查資料,有的說是內存不足,我在本地測試時,循環申請內存都不是問題,因此不是內存不足的原因。。
後來就和團隊成員進行商量,考慮到了多線程原因引起的,但是沒有確鑿證據,不知malloc等函數是線程安全還是線程不安全的。。於是後來就對malloc和free函數進行了加鎖操作。。運行幾天,並沒有出現異常。。。
至此,這個問題也基本解決了,但是仔細想一想,別人在開發C語言程序時,如果是多線程時,都要對C函數進行加鎖操作嗎?
最後,在成員們和老大們開會時,老大們一針見血的對該問題提出了意見:在VC工程中,設置其C Runtime 版本為多線程版本即可,原來如此啊。。。
設置如下圖所示(在工程設置裡,VC6.0默認是單線程的。。。無語中。。):
下班回來後,特定查了下資料和書籍,心中的疑惑也就解開了,原文如下:
什麼是C Runtime 函數庫的多線程版本
當C runtime 函數庫於1970s 年代產生出來時,PC 的內存容量還很小,多任務是
個新奇觀念,更別提什麼多執行線程了。因此以當時產品為基礎所演化的C runtime 函
數庫在多線程(multithreaded)的表現上有嚴重問題,無法被多線程程序使用。
利用各種同步機制(synchronous mechanism)如critical section、mutex、semaphore、
event,可以重新開發一套支持多執行線程的runtime 函數庫。問題是,加上這樣的能
力,可能導至程序代碼大小和執行效率都遭受不良波及-- 即使你只激活了一個執行
線程。
Visual C++ 的折衷方案是提供兩種版本的C runtime 函數庫。一種版本給單線程程序
使用,一種版本給多線程程序使用。多線程版本的重大改變是,第一,變量如errno 者
現在變成每個執行線程各擁有一個。第二,多線程版中的數據結構以同步機制加以保護。
Visual C++ 一共有六個C runtime 函數庫產品供你選擇:
Single-Threaded(static) libc.lib 898,826
Multithreaded(static) libcmt.lib 951,142
Multithreaded DLL msvcrt.lib 5,510,000
Debug Single-Threaded(static) libcd.lib 2,374,542
Debug Multithreaded(static)libcmtd.lib 2,949,190
Debug Multithreaded DLL msvcrtd.lib 803,418
Visual C++ 編譯器提供下列選項,讓我們決定使用哪一個C runtime 函數庫:
/ML Single-Threaded(static)
/MT Multithreaded(static)
/MD Multithreaded DLL(dynamic import library)
/MLd Debug Single-Threaded(static)
/MTd Debug Multithreaded(static)
/MDd Debug Multithreaded DLL(dynamic import library)