{"id":168,"date":"2007-11-28T18:24:42","date_gmt":"2007-11-28T17:24:42","guid":{"rendered":"http:\/\/blog.m-ri.de\/index.php\/2007\/11\/28\/createthread-und-die-crt\/"},"modified":"2007-11-28T10:07:30","modified_gmt":"2007-11-28T09:07:31","slug":"createthread-und-die-crt","status":"publish","type":"post","link":"http:\/\/blog.m-ri.de\/index.php\/2007\/11\/28\/createthread-und-die-crt\/","title":{"rendered":"CreateThread und die CRT"},"content":{"rendered":"<p>Immer wieder sehe ich Code Snippets die CreateThread verwenden.<br \/>\nImmer wieder antworte ich gleichlautend:<\/p>\n<blockquote><p>Vermeide CreateThread, wenn Du CRT Funktionen verwendest, das erzeugt Leaks in der CRT.<br \/>\nVerwende deshalb immer nur <a href=\"http:\/\/msdn2.microsoft.com\/en-US\/library\/kdzttdcb(VS.80).aspx\">_beginthread(ex)<\/a>. \u2757<\/p><\/blockquote>\n<p>Irgendwie glauben viele\u00a0Programmierer, dass es besser ist eine m\u00f6glichst OS-nahe Funktion zu verwenden. In diesem Fall ist es es definitiv nicht ratsam, denn droht in diesem Fall ein <strong>Speicherleck von um die 530Bytes <\/strong>(in <em>VC-2005<\/em>) pro beendetem Thread.<\/p>\n<p>In K\u00fcrze: Das ganze Problem liegt darin, dass bestimmte CRT Funktionen thread lokalen Speicher ben\u00f6tigen. Dieser wird im <em>TLS <\/em>(<em>Thread Local Storage<\/em>) bei Bedarf angelegt und entsorgt wenn die Threadfunktion returniert oder mit <em>_endthread <\/em>beendet wird.<br \/>\nGleiches gilt, wenn der Thread mit <em>ExitThread<\/em> oder <em>TerminateThread <\/em>beendet wird! (Das <em>TerminateThread<\/em> sowieso nicht in Frage kommen darf weil es noch \u00fcbleres tut wei\u00df ja hoffentlich sowieso jeder \ud83d\ude09 )<\/p>\n<p>Hier eine entsprechende Sammlung der\u00a0entsprechenden Dokumentationen mit den Begr\u00fcndungen:\u00a0<\/p>\n<p><strong><a href=\"http:\/\/www.amazon.de\/Advanced-Windows-Jeffrey-Richter\/dp\/1572315482\">Jeffrey Richter &#8222;Advanced Windows&#8220; 3rd Edition<\/a><br \/>\n<\/strong>Kapitel 4, &#8222;Processes, Threads and the C Run-Time Library&#8220; Seite 108 folgende.<\/p>\n<p><strong>CreateThread Doku: <\/strong><a href=\"http:\/\/msdn2.microsoft.com\/En-US\/library\/ms682453.aspx\">http:\/\/msdn2.microsoft.com\/En-US\/library\/ms682453.aspx<\/a><\/p>\n<blockquote><p>A thread in an executable that calls the C run-time library (CRT) should use the <strong>_beginthreadex<\/strong> and <strong>_endthreadex<\/strong> functions for thread management rather than <strong>CreateThread<\/strong> and <strong>ExitThread<\/strong>; this requires the use of the multi-threaded version of the CRT. If a thread created using <strong>CreateThread<\/strong> calls the CRT, the CRT may terminate the process in low-memory conditions.<\/p><\/blockquote>\n<p><strong>ExitThread Doku: <\/strong><a href=\"http:\/\/msdn2.microsoft.com\/en-us\/library\/ms682659.aspx\"><strong>http:\/\/msdn2.microsoft.com\/en-us\/library\/ms682659.aspx<\/strong><\/a><\/p>\n<blockquote><p>A thread in an executable that is linked to the static C run-time library (CRT) should use <strong>_beginthread<\/strong> and <strong>_endthread <\/strong>for thread management rather than <strong>CreateThread<\/strong> and <strong>ExitThread<\/strong>. Failure to do so results in small memory leaks when the thread calls <strong>ExitThread<\/strong>. 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 <a href=\"http:\/\/msdn2.microsoft.com\/en-us\/library\/ms682579.aspx\">DisableThreadLibraryCalls<\/a> function. Otherwise, it is safe to call <strong>CreateThread <\/strong>and <strong>ExitThread <\/strong>from a thread in a DLL that links to the static CRT.<\/p><\/blockquote>\n<p><strong>KB-Artikel 104641: <\/strong><a href=\"http:\/\/support.microsoft.com\/kb\/104641\/en-us\">http:\/\/support.microsoft.com\/kb\/104641\/en-us<\/a><\/p>\n<blockquote><p>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.<\/p>\n<p>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().<\/p>\n<p><strong>Note It is not possible to terminate a thread with _endthreadex() when it was created with CreateThread(). \u2757<\/strong><\/p><\/blockquote>\n<p><strong>\u2757 Anmerkung: <\/strong>Dieser KB artikel ist leider unvollst\u00e4ndig. Hier werden nur ein paar time Funktionen aufgelistet, es trifft aber weitaus mehr Funktionen wie <em>errno, strtok, strerror, tmpname, tmpfile, _ecvt, _fcvt, <\/em>alle Funktionen die _errno oder _doserrno nutzen\u00a0etc.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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). \u2757 Irgendwie glauben viele\u00a0Programmierer, dass es besser ist eine m\u00f6glichst OS-nahe Funktion zu verwenden. In diesem Fall ist es es definitiv nicht ratsam, &hellip; <a href=\"http:\/\/blog.m-ri.de\/index.php\/2007\/11\/28\/createthread-und-die-crt\/\" class=\"more-link\"><span class=\"screen-reader-text\">\u201eCreateThread und die CRT\u201c <\/span>weiterlesen<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[30,3,2],"tags":[360,61],"class_list":["post-168","post","type-post","status-publish","format-standard","hentry","category-c","category-programmieren","category-windows-api","tag-crt","tag-winapi"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/posts\/168","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/comments?post=168"}],"version-history":[{"count":0,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/posts\/168\/revisions"}],"wp:attachment":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/media?parent=168"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/categories?post=168"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/tags?post=168"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}