{"id":357,"date":"2008-11-04T20:30:59","date_gmt":"2008-11-04T19:30:59","guid":{"rendered":"http:\/\/blog.m-ri.de\/?p=357"},"modified":"2009-08-10T14:14:55","modified_gmt":"2009-08-10T12:14:55","slug":"vs-tipps-tricks-heap-bugs-finden-teil-3","status":"publish","type":"post","link":"http:\/\/blog.m-ri.de\/index.php\/2008\/11\/04\/vs-tipps-tricks-heap-bugs-finden-teil-3\/","title":{"rendered":"VS Tipps &#038; Tricks: Heap Bugs finden (Teil 3)"},"content":{"rendered":"<p>Mancher Bug macht einem nicht den Gefallen und l\u00e4sst sich in der Debug-Version finden. Ursache ist oft genug eine Variable, die in der Debug-Version initialisiert (0xCC) wird aber in der Release-Version zu einem Crash f\u00fchrt, wenn zuf\u00e4llige Daten auf dem Stack f\u00fcr undefiniertes Verhalten sorgen.<\/p>\n<p>Also macht man sich an das debuggen der Release Version und kann keinen Fehler finden.<br \/>\nKaum startet man das Programm ohne Debugger dann kracht es wieder. Warum?<\/p>\n<p>Manch einer k\u00f6nnte jetzt denken: Der Debugger ver\u00e4ndert das Memory Layout! Das tut er schon, aber entscheidend f\u00fcr ein anderes Verhalten ist\u00a0der Debug Heap!<br \/>\nDie wenigsten Entwickler wissen \u00fcberhaupt, dass es ihn gibt. Ich meine hier nicht die Debug Funktionen, die die CRT zur Verf\u00fcgung stellt, denn mein Thema heute ist ja das Debuggen eines Release-Programms, und die Debug-CRT hat ja bekanntlich in einem Release Programm nichts zu suchen!<\/p>\n<p>Machen wir es praktisch und nehmen wieder mein kleines Crashtest-Programm:<\/p>\n<pre lang=\"cpp\">#include &lt;windows.h&gt;\r\n#include &lt;tchar.h&gt;\r\n#include &lt;crtdbg.h&gt;\r\nint _tmain(int argc, _TCHAR* argv[])\r\n{\r\n  char *pCorrupt = new char[100];\r\n  ZeroMemory(pCorrupt,104);\r\n  char *pOther = new char[100];\r\n  ZeroMemory(pOther,100);\r\n  delete [] pOther;\r\n  delete [] pCorrupt;\r\n  return 0;\r\n}<\/pre>\n<p>Wenn wir dieses Programm als Release Version kompilieren und ausf\u00fchren, dann erhalten wir keine Fehlermeldung \u2757 Interessant. Der Heap ist nicht soweit zerst\u00f6rt, dass es zu einer Zugriffsverletzung kommt. Starten wir aber unser Programm mit dem Debugger, dann wird der so genannte Debug Heap des Systems verwendet, der wie die Debug-CRT Guardbytes setzt und kontrolliert.<\/p>\n<p>Ein weiteres Problem entsteht dadurch, dass der Debug Heap den allokierten Speicher auf feste Werte initialisiert genau wie die Debugversion der CRT. Wenn also nicht initialisierter Speicher genutzt wird, dann ist das Verhalten mit dem Debug-Heap deterministisch, ohne Debug Heap eher zuf\u00e4llig.<\/p>\n<p>Das im Debugger alles etwas anders sein kann ist sogar <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/cc266414.aspx\">dokumentiert<\/a> \ud83d\ude09<\/p>\n<blockquote><p>Processes that the debugger creates (also known as spawned processes) behave slightly differently than processes that the debugger does not create.<br \/>\nInstead of using the standard heap API, processes that the debugger creates use a special debug heap. On Microsoft Windows XP and later versions of Windows, you can force a spawned process to use the standard heap instead of the debug heap by using the _NO_DEBUG_HEAP environment variable or the -hd command-line option.<\/p><\/blockquote>\n<p>In diesem Text steht auch, wie man den Debug-Heap ausschalten kann, mit:<\/p>\n<pre lang=\"bat\">SETX _NO_DEBUG_HEAP 1<\/pre>\n<p>Diese Environment-Variable sorgt daf\u00fcr, dass sich auch bei geladenem Debugger, das Programm so verh\u00e4lt wie ohne Debugger (hoffentlich). F\u00fchrt man mein Testprogramm nun im Debugger aus, wenn die Environment-Variable <em>_NO_DEBUG_HEAP <\/em>auf 1 gesetzt ist, erh\u00e4lt man keinen Debug-Break mehr. Denn in diesem Fall gibt es keine Guardbytes, die gepr\u00fcft werden.<br \/>\nL\u00f6scht man den Eintrag <em>_NO_DEBUG_HEAP <\/em>wieder, dann erh\u00e4lt man im Debugger wieder wie erwartet einen Break.<\/p>\n<p>Will man also wirklich realit\u00e4tsnah eine Release-Version debuggen, dann kommt man um das Ausschalten des Debug-Heaps nicht herum.<\/p>\n<p>PS: Man kann es auch etwas einfacher haben, wenn man sich nachtr\u00e4glich an den Prozess mit dem Debugger attached (wenn das geht). Ideal ist dieses Verfahren auch beim Remote-Debugging (dazu demn\u00e4chst mehr).<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Mancher Bug macht einem nicht den Gefallen und l\u00e4sst sich in der Debug-Version finden. Ursache ist oft genug eine Variable, die in der Debug-Version initialisiert (0xCC) wird aber in der Release-Version zu einem Crash f\u00fchrt, wenn zuf\u00e4llige Daten auf dem Stack f\u00fcr undefiniertes Verhalten sorgen. Also macht man sich an das debuggen der Release Version &hellip; <a href=\"http:\/\/blog.m-ri.de\/index.php\/2008\/11\/04\/vs-tipps-tricks-heap-bugs-finden-teil-3\/\" class=\"more-link\"><span class=\"screen-reader-text\">\u201eVS Tipps &#038; Tricks: Heap Bugs finden (Teil 3)\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":[25,30,19,11,4,3,31,2],"tags":[370,38,352,136,37,61],"class_list":["post-357","post","type-post","status-publish","format-standard","hentry","category-atl","category-c","category-crt","category-debugging","category-mfc","category-programmieren","category-vs-tipps-tricks","category-windows-api","tag-c","tag-debuggen","tag-mfc","tag-qualitaetssicherung","tag-vs-tippstricks","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\/357","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=357"}],"version-history":[{"count":1,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/posts\/357\/revisions"}],"predecessor-version":[{"id":358,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/posts\/357\/revisions\/358"}],"wp:attachment":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/media?parent=357"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/categories?post=357"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/tags?post=357"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}