CreateThread und die CRT

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.

ATE beim „Ready for take off“ in Frankfurt vom 19.-21.02.2008

Wer mich mal persönlich kennen lernen will, der kann mich in Frankfurt beim großen Launch “Ready for take off” von Windows Server 2008, SQL Server 2008 und Visual-Studio 2008 vom 19.-21. Februar 2008 treffen.

Ich werde einer der vielen MVPs sein, die als ATEs (Ask the Experts) die Veranstaltung begleiten.

VC-2008: Neues, Breaking changes…

Hier ein kleiner Auszug aus der Liste der Änderungen und Neuigkeiten.
Die Links verweisen in die MSDN wo man alles nachlesen kann.

What’s New in Visual C++ 2008
Da ist nicht sooo viel:

  • Eingeschränkte (read only) Unterstützung des Class Designers.
  • Vista style Guidlines für Dialoge
  • Vista Common Controls in der MFC
  • Die interessanten Sachen wie MFCNext und TR1 kommen noch

Breaking Changes

  • Nachdem in Visual Studio 2005 der Support von Windows  95 entfiel, hat Microsoft nun einen Schlussstrich unter gezogen.
    Im Klartext: Windows 95, Windows 98, Windows ME, und Windows NT werden als Zielplattformen nicht mehr unterstützt.
  • Hier fällt auf, dass die ATL nun zwingend Abhängig von der CRT wird. Wer früher gerne ATL_MIN_CRT verwendet hat um „gar keine“ CRT zu verwenden, der wird feststellen, dass seine Module etwas wachsen.
  • /Wp64 ist deprecated (na endlich)…

Anmerkung:
Wie so oft werden hier die Sachen veröffentlicht, wo man bei Microsoft weiß, dass man Breaking Changes durchgeführt hat. Es gibt oft genug weitere Breaking Changes die man oft erst am eigenen Leib erfahren muss, siehe Attributed ATL.

Weitere Infos zur MFC in VS-2008 und der BCG Pro-Library

Hier noch ein paar Infos zu dem Thema:

Eine Microsoft Bekanntmachung auf den US VC++ Seiten: MFC Update Powered By BCGSoft
http://msdn2.microsoft.com/de-de/visualc/bb892882.aspx

Eine Pressemitteilung von BCG-Soft vom 09.11.2007:
http://www.bcgsoft.com/pressreleases/PR071110.pdf

Fragen und Antworten im BCG-Forum:
http://www.bcgsoft.com/cgi-bin/forum/topic.asp?TOPIC_ID=4476

VS-Tipps & Tricks: Einstellungen für Visual Studio mehreren Arbeitsplätzen gleich halten

Das man Einstellungen von Visual Studio mittlerweile einfach und intelligent ex- und importieren lassen ist ja mittlerweile bekannt. Man findet diese Funktion direkt im Tools Menü. In meinem Blog fand dies auch schon Erwähnung.

Weitaus versteckter in den Einstellungen von Visual Studio findet man unter
Tools -> Environment -> Import and Export Settings
einen Schalter der das heißt: Use team settings file

Hier ist ein Feature verborgen, dass es wirklich einfach macht auch in einem Team identische Projekt und Visual Studio Einstellungen auf jedem Arbeitsplatz einzustellen. Und das mit wirklich geringem administrativen Aufwand.
Gerade die Include und Library Pfade für gemeinsame Bibliotheken und deren Reihenfolge lassen sich direkt vorbelegen. Und sie werden bei jedem Neustart von Visual Studio auf den vorbestimmten Wert zurückgestellt.
Vorbei die Suche warum in aller Welt irgendwelche falschen SDK Header und Libraries verwendet werden. Warum ein Entwickler immer noch eine uralte Libary eines Drittanbieters verwendet und in seinen Modulen ein Bug auftaucht, den alle schon überwunden glaubten.
Voraussetzungen dafür ist natürlich, dass die einzelnen Rechner der Entwickler natürlich ein ähnliches Verzeichnis Layout verwenden, bzw. die gemeinsamen Bibliotheken im Netz liegen.

Im Prinzip lässt sich jede Einstellung von VS auf diesem Wege beeinflussen.

Der IE 7 und weiterrolleneiner Bildschirmseite…

Da arbeite ich schon seit Jahren mit dem IE, und schätze mich als Tastaturfan ein, der alle möglichen Hotkeys nutzt. Aber jetzt musste mir meine elfjährige Tochter Lea den simpelsten Trick zeigen, wie man auf einer Internetseite einen Bildschirmauschnitt weiter rollen kann… mit der Leertaste! 😯

Und es kommt noch besser mit Umschalt+Leertaste kann man eine Bildschirmseite hoch blättern.

Mir waren diese Hotkeys aus dem Adobe Acrobat Reader bekannt, aber dass der IE diese Hotkeys auch benutzt war mir neu. Vielleicht auch einem von Euch…

Jetzt ist es soweit VS-2008 kommt nächste Woche als MSDN-Download

Der Termin der ursprünglich genannt wurde für die Veröffentlichung von Visual-Studio 2008 (Orcas) wird wirklich eingehalten.

Im MSDN-Subscriptions Weblog wurde gestern bekannt gegeben, dass VS-2008 ab Anfang nächster Woche veröffentlicht wird.

Damit ist es das erste Produkt für die Launch Veranstaltung im Februar 2008 „Ready for Take Off“, das auch wirklich fertig ist…

VS-Tipps & Tricks: Tracepoints die zweite…

In meinen ersten Artikel zu Tracepoints habe ich ja auch erwähnt, dass man sehr einfach auch Variablen ausgeben kann. Das schöne ist, dass dies sofort auch für Iteratoren und manche andere Klasse funktioniert, ohne dass man spezielle Member angeben muss. Man setzt einfach die Variable in geschweifte Klammern. Und das dürfen auch komplexe Ausdrücke sein, wie im Debug-Watch-Fenster.

So führt die folgende Tracepoint Definition in einem meiner Programme:

$FUNCTION, {iCountry,x} {s_countries[iCountry]}

zu der folgenden Ausgabe:

wmain(int, wchar_t * *, wchar_t * *), 1 {m_szISO3=0x00487e48 „AUT“ m_szISO2=0x00487e44 „AT“ m_szCountryCode=0x00487e40 „43“ }
wmain(int, wchar_t * *, wchar_t * *), 2 {m_szISO3=0x00487e3c „AUS“ m_szISO2=0x00487e38 „AU“ m_szCountryCode=0x00487e34 „61“ }

Ein leider undokumentiertes Feature von Tracepoints ist jedoch, dass innerhalb der geschweiften Klammern auch die bekannten Formatierungen aus dem Debug-Watch-Fenster verwendet werden können. Wie hier zum Beispiel um die Ausgabe des Intergers in hexadezimal zu ändern:

$FUNCTION, {iCountry,x} {s_countries[iCountry]}

wmain(int, wchar_t * *, wchar_t * *), 0x00000001 {m_szISO3=0x00487e48 „AUT“ m_szISO2=0x00487e44 „AT“ m_szCountryCode=0x00487e40 „43“ }
wmain(int, wchar_t * *, wchar_t * *), 0x00000002 {m_szISO3=0x00487e3c „AUS“ m_szISO2=0x00487e38 „AU“ m_szCountryCode=0x00487e34 „61“ }

Besonders ist das interessant, wenn Fensterprozeduren tracen möchte ohne das Trace-Tool oder Spy++ verwenden will und man die Formatspezifkation wm verwendet und alle Fensternachrichten im Klartext lesen kann. Oder man verwendet hr und sieht auch einen HRESULT nicht mehr nur als kryptische Zahl.