{"id":351,"date":"2008-10-27T22:47:21","date_gmt":"2008-10-27T21:47:21","guid":{"rendered":"http:\/\/blog.m-ri.de\/?p=351"},"modified":"2008-10-27T22:47:21","modified_gmt":"2008-10-27T21:47:21","slug":"vs-tipps-tricks-heap-bugs-finden-teil-1","status":"publish","type":"post","link":"http:\/\/blog.m-ri.de\/index.php\/2008\/10\/27\/vs-tipps-tricks-heap-bugs-finden-teil-1\/","title":{"rendered":"VS Tipps &#038; Tricks: Heap Bugs finden (Teil 1)"},"content":{"rendered":"<p>Probleme finden, die mit dem Heap zusammenh\u00e4ngen ist oft genug eine Sache f\u00fcr sich und f\u00fcr Anf\u00e4nger nicht selten ein Buch mit sieben Siegeln. Die CRT und der Debugger stellen aber einige Werkzeuge zur Verf\u00fcgung, die es einem doch mit etwas Geschick und Wissen\u00a0erlauben auch komplexere versteckte Fehler zu finden, die Heapfehler ausl\u00f6sen.<\/p>\n<p>Jeder C\/C++ Entwickler hat schon Meldungen dieser Art beim Testen seiner Programme gesehen:<\/p>\n<blockquote><p>HEAP[CrashTest.exe]: Heap block at 006D7920 modified at 006D79B0 past requested size of 88<br \/>\nWindows has triggered a breakpoint in CrashTest.exe.<br \/>\nThis may be due to a corruption of the heap, which indicates a bug in CrashTest.exe or any of the DLLs it has loaded.\u00a0<\/p><\/blockquote>\n<p>oder etwas in dieser Art:<\/p>\n<blockquote><p>Debug Error!<br \/>\nProgram: &#8230;nts\\Visual Studio 2008\\Projects\\CrashTest\\Debug\\CrashTest.exe<br \/>\nHEAP CORRUPTION DETECTED: after Normal block (#110) at 0x000D7948.<br \/>\nCRT detected that the application wrote to memory after end of heap buffer.<\/p><\/blockquote>\n<p>Ursache ist ein Fehler wie in diesem kleinen Beispielprogramm:<\/p>\n<pre lang=\"cpp\" line=\"1\">#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,106); \/\/ -- This will corrupt the heap \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 die Debug-CRT benutzt wird erh\u00e4lt man automatisch einen Break im Debugger wenn der Speicherblock pCorrupt freigeben wird (Zeile 11). Man braucht also nur den Call-Stack oder Stacktrace anzusehen und kann zumindest feststellen, welcher Block defekt ist.<\/p>\n<p>Schwieriger wird es\u00a0dann schon die Stelle zu finden, an der der Block \u00fcberschrieben wird. In meinem Beispiel also die Zeile 7. Besonders dann wird es komplex, wenn das Programm gr\u00f6\u00dfer ist, und der Speicherblock an evtl. sehr vielen Stellen genutzt wird.<\/p>\n<p>Um die Position einzugrenzen und nicht evtl. bis zum Programmende warten zu m\u00fcssen, wenn man (hoffentlich) alle Objekte freigibt kann man die CRT veranlassen den Heap zu pr\u00fcfen. Dies geschieht\u00a0mit <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/e73x0s4b.aspx\">_CrtCheckMemory <\/a>oder <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/y1132dee(VS.80).aspx\">AfxCheckMemory<\/a>.<br \/>\nStreut man also in seinem Code an strategisch guten Stellen das folgende Statement in seinen Code<\/p>\n<pre lang=\"cpp\">ASSERT(AfxCheckMemory()); \/\/ oder _CrtCheckMemory<\/pre>\n<p>kann man relativ gut die Stelle einkreisen die den Fehler verursacht, und das ohne gro\u00dfe Performanceverluste. Man erh\u00e4lt sofort einen <em>ASSERT<\/em>, ab dem Moment ab dem die Integrit\u00e4t des Heaps zerst\u00f6rt wurde und der Check durchgef\u00fchrt wird.<\/p>\n<p>Noch etwas einfacher ist es, die CRT dazu zu bringen sich sofort zu melden wenn der Heap zerst\u00f6rt wird. Dies kann man erreichen indem man das Debug-Flag <em>_CRTDBG_CHECK_ALWAYS_DF<\/em> setzt.<\/p>\n<p>Platziert man bei Programmstart die folgende Codezeile in seinem Programm<\/p>\n<pre lang=\"cpp\">_CrtSetDbgFlag(_CrtSetDbgFlag(0)|_CRTDBG_CHECK_ALWAYS_DF);<\/pre>\n<p>dann unterbricht die <em>CRT <\/em>das Programm sofort bei der n\u00e4chsten Allokation eines Speicherbocks, nachdem der Heap zerst\u00f6rt wurde. In meinem Beispiel also direkt bei der n\u00e4chsten Allokation in Zeile 8!<br \/>\nNachteil ist, dass bei jeder Allokation der Heap gepr\u00fcft wird und damit die Performance schon in den Keller gehen kann, wenn das Programm gro\u00df ist und der Fehler evtl. selten auftritt.<\/p>\n<p>Man kann also mit den einfachen Bordmitteln der CRT einen Fehler schon relativ leicht eingrenzen.<\/p>\n<p>Soweit f\u00fcr heute. Was man noch alles machen kann um effektiv Heap-Fehler zu finden werde ich demn\u00e4chst noch in weiteren Artikeln zu diesem Thema beschreiben.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Probleme finden, die mit dem Heap zusammenh\u00e4ngen ist oft genug eine Sache f\u00fcr sich und f\u00fcr Anf\u00e4nger nicht selten ein Buch mit sieben Siegeln. Die CRT und der Debugger stellen aber einige Werkzeuge zur Verf\u00fcgung, die es einem doch mit etwas Geschick und Wissen\u00a0erlauben auch komplexere versteckte Fehler zu finden, die Heapfehler ausl\u00f6sen. Jeder C\/C++ &hellip; <a href=\"http:\/\/blog.m-ri.de\/index.php\/2008\/10\/27\/vs-tipps-tricks-heap-bugs-finden-teil-1\/\" class=\"more-link\"><span class=\"screen-reader-text\">\u201eVS Tipps &#038; Tricks: Heap Bugs finden (Teil 1)\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":[1,25,30,19,11,4,3,31],"tags":[370,360,38,143,37,61],"class_list":["post-351","post","type-post","status-publish","format-standard","hentry","category-allgemein","category-atl","category-c","category-crt","category-debugging","category-mfc","category-programmieren","category-vs-tipps-tricks","tag-c","tag-crt","tag-debuggen","tag-heap","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\/351","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=351"}],"version-history":[{"count":0,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/posts\/351\/revisions"}],"wp:attachment":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/media?parent=351"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/categories?post=351"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/tags?post=351"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}