Immer wieder sehe ich Code Snippets die CreateThread verwenden.
Immer wieder antworte ich gleichlautend:
Vermeide CreateThread, wenn Du CRT Funktionen verwendest, das erzeugt Leaks in der CRT.
Verwende deshalb immer nur _beginthread(ex). ❗
Irgendwie glauben viele Programmierer, dass es besser ist eine möglichst OS-nahe Funktion zu verwenden. In diesem Fall ist es es definitiv nicht ratsam, denn droht in diesem Fall ein Speicherleck von um die 530Bytes (in VC-2005) pro beendetem Thread.
In Kürze: Das ganze Problem liegt darin, dass bestimmte CRT Funktionen thread lokalen Speicher benötigen. Dieser wird im TLS (Thread Local Storage) bei Bedarf angelegt und entsorgt wenn die Threadfunktion returniert oder mit _endthread beendet wird.
Gleiches gilt, wenn der Thread mit ExitThread oder TerminateThread beendet wird! (Das TerminateThread sowieso nicht in Frage kommen darf weil es noch übleres tut weiß ja hoffentlich sowieso jeder 😉 )
Hier eine entsprechende Sammlung der entsprechenden Dokumentationen mit den Begründungen:
Jeffrey Richter „Advanced Windows“ 3rd Edition
Kapitel 4, „Processes, Threads and the C Run-Time Library“ Seite 108 folgende.
CreateThread Doku: http://msdn2.microsoft.com/En-US/library/ms682453.aspx
A thread in an executable that calls the C run-time library (CRT) should use the _beginthreadex and _endthreadex functions for thread management rather than CreateThread and ExitThread; this requires the use of the multi-threaded version of the CRT. If a thread created using CreateThread calls the CRT, the CRT may terminate the process in low-memory conditions.
ExitThread Doku: http://msdn2.microsoft.com/en-us/library/ms682659.aspx
A thread in an executable that is linked to the static C run-time library (CRT) should use _beginthread and _endthread for thread management rather than CreateThread and ExitThread. Failure to do so results in small memory leaks when the thread calls ExitThread. Another work around is to link the executable to the CRT in a DLL instead of the static CRT. Note that this memory leak only occurs from a DLL if the DLL is linked to the static CRT and a thread calls the DisableThreadLibraryCalls function. Otherwise, it is safe to call CreateThread and ExitThread from a thread in a DLL that links to the static CRT.
KB-Artikel 104641: http://support.microsoft.com/kb/104641/en-us
Threads that are created and terminated with the CreateThread() and ExitThread() Win32 API functions do not have memory that is allocated by the CRT for static data and static buffers cleaned up when the thread terminates. Some examples of this type of memory are static data for errno and _doserrno and the static buffers used by functions such as asctime(), ctime(), localtime(), gmtime(), and mktime(). Using CreateThread() in a program that uses the CRT (for example, links with LIBCMT.LIB) may cause a memory leak of about 70-80 bytes each time a thread is terminated.
To guarantee that all static data and static buffers allocated by the CRT are cleaned up when the thread terminates, _beginthreadex() and _endthreadex() should be used when creating a thread. The _beginthreadex() function includes the same parameters and functionality as CreateThread().
Note It is not possible to terminate a thread with _endthreadex() when it was created with CreateThread(). ❗
❗ Anmerkung: Dieser KB artikel ist leider unvollständig. Hier werden nur ein paar time Funktionen aufgelistet, es trifft aber weitaus mehr Funktionen wie errno, strtok, strerror, tmpname, tmpfile, _ecvt, _fcvt, alle Funktionen die _errno oder _doserrno nutzen etc.
Gilt die CRT-Einschränkung neben CreateThread auch für SetTimer?
Danke.
Nein! Warum auch. SetTimer erzeugt keinen neuen Thread!
Allerdings würde ich auch bei einem neuen UI Thread niemals CreateThread benutzen.