2012-08-04 77 views
3

所以我明白CreateThread和CRT會導致內存泄漏,信號不起作用,並且應該使用_beginthread或_beginthreadex函數。當編寫一個應用程序時,這一切都很好,但是那些爲其他應用程序編寫dll等的應用程序(無論是普通的c dll,com對象,插件等)如何。沒有辦法保證如何創建一個調用DLL的線程,即使他們使用了__beginthread(ex),它很可能打賭他們有不同的CRT實現\版本。線程創建,CRT和DLL的意圖是如何完成的?

那麼程序員應該怎麼做呢?不使用CRT?產生一個內部線程並將所有工作卸載到該線程上(不使用調用線程的CRT)?使用DllMain和attach/detach的一些技巧來正確設置和關閉所有線程,無論它們是如何創建的?

回答

1

有兩種選擇:

  1. 不要從DLL中使用CRT。
  2. 發送多個DLL,每個支持的工具鏈版本一個。

如果1不是可接受的解決方案,則選擇2。請注意,無論如何,您必須運送多個DLL。如果您的用戶編譯32位 64位體系結構。

+0

32/64位很簡單,並且趨於明確。但是大多數應用程序似乎沒有說(例如,如果從.NET中調用,或者從Windows的一部分(如explorer.exe)調用會發生什麼情況?即使安裝程序檢測到並設置了正確的dll,系統更新可能不會並打破它仍然?)。在沒有CRT的情況下創建這樣的東西似乎並不實際,是否真的沒有辦法解決這個問題(也許是一個開放源代碼的C和C++標準庫,在沒有這些問題的情況下可以實現?) – 2012-08-04 12:45:14

+0

@FireLancer:如果你在討論插件和例如,一種選擇是在單獨的EXE中創建服務,並讓該DLL成爲與EXE進行通信的薄層。 – ybungalobill 2012-08-04 13:41:22

+0

@FireLancer:我也想知道你用什麼CRT的功能可能會導致問題..?如果你寫了一個插件,那麼無論如何你都不能玩這個全局狀態。其他的東西像'sprintf','std :: vector'等等都可以正常工作。另外根據我的知識,CreateThread + CRT的內存泄漏有點過時了。 [當前文檔](http://msdn.microsoft.com/en-us/library/windows/desktop/ms682453%28v=vs.85%29.aspx)只是說:「如果CRT可能會在內存不足的情況下終止進程。「按照在一個進程中加載​​兩個CRT版本,它*通常*工作正常。 – ybungalobill 2012-08-04 13:48:38

6

的CreateThread和CRT會導致內存泄漏

不,這是一個誤區,認爲是非常困難的因爲某些原因擺脫。在上個世紀使用_beginthread()是必要的,VS6是VS的最後一個版本,它仍然需要CRT。

這個問題已經得到解決,不足以解決對Windows 2000中線程池的支持問題。顯然,在CRT中無法處理它們,這些線程是由操作系統本身啓動的。實施非常簡單。無論CRT需要線程局部變量(如strtok()所需的變量),它首先檢查TLS存儲是否已分配給線程。如果不是,它會即時分配。

只需使用CreateThread()而不用擔心,當然假設你不再使用14歲的編譯器。

+0

剛剛遇到別的。 「fiX」是在CRT DLL中使用DllMain(線程附加/分離的東西),當人們堅持使用靜態crt構建時(因爲處理redist文件顯然對他們來說太費勁了......) ) – 2012-08-05 10:19:50

+0

嗯,我只是碰到了這個:http://blog.aaronballman.com/2011/09/threading-on-windows/這是一個有趣的閱讀。事實證明,使用帶有CRT的'CreateThread',你在水中仍然不是完全安全的。謹慎和正確理解你在做什麼仍然適用。 – 2013-03-13 11:23:02

+0

這正是那種半熟的博客文章,它很難擺脫這個神話。查看CRT源代碼,看看它在線程終止時如何使用FlsAlloc回調來釋放內存。 – 2013-03-13 12:01:09