{"id":113,"date":"2022-08-28T13:31:32","date_gmt":"2022-08-28T04:31:32","guid":{"rendered":"http:\/\/blog.tmyymmt.net\/en\/?p=113"},"modified":"2022-08-28T13:36:17","modified_gmt":"2022-08-28T04:36:17","slug":"how-to-detect-memory-leaks-in-c","status":"publish","type":"post","link":"https:\/\/blog.tmyymmt.net\/en\/?p=113","title":{"rendered":"How to detect memory leaks in C++"},"content":{"rendered":"<p><em><a href=\"https:\/\/blog.tmyymmt.net\/ja\/?p=141\">The original article of this in Japanese<\/a> was written in 2007, so the content may be outdated and unusable.<\/em><\/p>\n<p>A memory leak occurred in a project that use C++ on Linux.<br \/>\nI tried to use&nbsp;<a href=\"http:\/\/www.google.co.jp\/search?q=MemProf\">MemProf<\/a>\u3001<a href=\"http:\/\/www.google.co.jp\/search?q=mtrace\">mtrace<\/a>\u3001<a href=\"http:\/\/www.google.co.jp\/search?q=ccmalloc\">ccmalloc<\/a>\u3001<a href=\"http:\/\/www.google.co.jp\/search?q=mpatrol\">mpatrol<\/a>\u3001and <a href=\"http:\/\/www.google.co.jp\/search?q=dmalloc\">dmalloc<\/a>, but only mtrace was available in the project environment.<\/p>\n<p>However, in the case of new\/delete, the existence of the leak was confirmed, but the source file name and line number were not output (in the case of malloc\/free, even the line number is output). It seems that dmalloc can be used with c++ new\/delete, but when I tried to link it with the target program, I got a link error and cannot use it.<\/p>\n<p>After looking up the relevant information, I had no choice, so I tried to write the code myself.<\/p>\n<ul>\n<li><a href=\"http:\/\/tmyymmt.net\/cpp\/memoryleaks\/DetectMemoryLeaks.h\">DetectMemoryLeaks.h<\/a><\/li>\n<li><a href=\"http:\/\/tmyymmt.net\/cpp\/memoryleaks\/DetectMemoryLeaks.cpp\">DetectMemoryLeaks.cpp<\/a><\/li>\n<li><a href=\"http:\/\/tmyymmt.net\/cpp\/memoryleaks\/MemoryLeaksSample.cpp\">MemoryLeaksSample.cpp<\/a><\/li>\n<\/ul>\n<p>The codes override or overload new, new[], delete, delete[], and check the correspondence at the time of memory allocation and release. If memory has been allocated but not released, the file name and line number on the source that allocated the memory are displayed.<br \/>\n1. Copy <a href=\"http:\/\/tmyymmt.net\/cpp\/memoryleaks\/DetectMemoryLeaks.h\">DetectMemoryLeaks.h<\/a> and <a href=\"http:\/\/tmyymmt.net\/cpp\/memoryleaks\/DetectMemoryLeaks.cpp\">DetectMemoryLeaks.cpp<\/a> to your project.<br \/>\n2. Add DetectMemoryLeaks.cpp to the target of compile.<br \/>\n3. Add the following codes at top of source code file which be compiled at first.<br \/>\n&nbsp;&nbsp;&nbsp; #include &#8220;MemoryLeakChecker.h&#8221;<br \/>\n&nbsp;&nbsp;&nbsp; #define new new(__FILE__, __LINE__ )<br \/>\n4. Add the following code at the start of the range where you want to check for memory leaks.<br \/>\n&nbsp;&nbsp;&nbsp; memoryLeakCheckerCheckStart(std::cout);<br \/>\n5. Add the following code at the end of the range where you want to check for memory leaks.<br \/>\n&nbsp;&nbsp;&nbsp; memoryLeakCheckerCheckEnd(std::cout);<br \/>\n6. Compile your codes, and run it.<br \/>\nExample to use.(<a href=\"http:\/\/tmyymmt.net\/cpp\/memoryleaks\/MemoryLeaksSample.cpp\">MemoryLeaksSample.cpp<\/a>)\u3002<br \/>\nNote: Multithreading is not considered, nesting of the detectMemoryLeaksStart\/End call is not considered.<\/p>\n<p><a href=\"http:\/\/tmyymmt.net\/cpp\/memoryleaks\/DetectMemoryLeaks.cpp\">DetectMemoryLeaks.cpp<\/a><\/p>\n<blockquote><p><span style=\"font-size: 0.8em;\">std::map detectMemoryLeaksMemoryMap;<br \/>\nbool detectMemoryLeaksFlag = false;<\/span><\/p>\n<p><span style=\"font-size: 0.8em;\">void *<br \/>\noperator new(std::size_t size, char * pszFileName, int nLineNum)<br \/>\nthrow (std::bad_alloc)<br \/>\n{<br \/>\nvoid * address = malloc(size);<br \/>\nif(address == 0)<br \/>\nthrow std::bad_alloc();<\/span><\/p>\n<p>if(detectMemoryLeaksFlag){<br \/>\n\/\/ std::cout &lt;&lt; &#8220;new: &#8221; &lt;&lt; pszFileName &lt;&lt; &#8220;:&#8221; &lt;&lt; nLineNum &lt;&lt; &#8221; size=&#8221; &lt;&lt; size &lt;&lt; &#8221; address=&#8221; &lt;&lt; address &lt;&lt; std::endl;<br \/>\nstd::ostringstream oss;<br \/>\noss &lt;&lt; pszFileName &lt;&lt; &#8220;:&#8221; &lt;&lt; nLineNum &lt;&lt; &#8221; size=&#8221; &lt;&lt; size&nbsp; &lt;&lt; &#8221; address=&#8221; &lt;&lt; address;<br \/>\ndetectMemoryLeaksMemoryMap.insert( std::pair((std::size_t)address, oss.str()) );<br \/>\n}<br \/>\nreturn address;<br \/>\n}<\/p>\n<p><span style=\"font-size: 0.8em;\">void *<br \/>\noperator new[](std::size_t size, char * pszFileName, int nLineNum)<br \/>\nthrow (std::bad_alloc)<br \/>\n{<br \/>\nvoid * address = malloc(size);<br \/>\nif(address == 0)<br \/>\nthrow std::bad_alloc();<\/span><\/p>\n<p>if(detectMemoryLeaksFlag){<br \/>\n\/\/ std::cout &lt;&lt; &#8220;new[]: &#8221; &lt;&lt; pszFileName &lt;&lt; &#8220;:&#8221; &lt;&lt; nLineNum &lt;&lt; &#8221; size=&#8221; &lt;&lt; size &lt;&lt; &#8221; address=&#8221; &lt;&lt; address &lt;&lt; std::endl;<br \/>\nstd::ostringstream oss;<br \/>\noss &lt;&lt; pszFileName &lt;&lt; &#8220;:&#8221; &lt;&lt; nLineNum &lt;&lt; &#8221; size=&#8221; &lt;&lt; size&nbsp; &lt;&lt; &#8221; address=&#8221; &lt;&lt; address;<br \/>\ndetectMemoryLeaksMemoryMap.insert( std::pair((std::size_t)address, oss.str()) );<br \/>\n}<br \/>\nreturn address;<br \/>\n}<\/p>\n<p><span style=\"font-size: 0.8em;\">void<br \/>\noperator delete(void * address)<br \/>\n{<br \/>\nif(address == 0) \/\/ Depends on environment.<br \/>\nreturn;<\/span><\/p>\n<p>if(detectMemoryLeaksFlag){<br \/>\n\/\/ std::cout &lt;&lt; &#8220;delete: &#8221; &lt;&lt; &#8221; address=&#8221; &lt;&lt; address &lt;&lt; std::endl;<br \/>\nstd::map::iterator it = detectMemoryLeaksMemoryMap.begin();<br \/>\nstd::map::iterator itEnd = detectMemoryLeaksMemoryMap.end();<br \/>\nstd::size_t checkAddress = (std::size_t)address;<br \/>\nfor(; it!=itEnd; it++){<br \/>\nif(it-&gt;first == checkAddress){<br \/>\ndetectMemoryLeaksMemoryMap.erase(it);<br \/>\nbreak;<br \/>\n}<br \/>\n}<br \/>\n}<br \/>\nfree(address);<br \/>\n}<\/p>\n<p><span style=\"font-size: 0.8em;\">void<br \/>\noperator delete[](void * address)<br \/>\n{<br \/>\nif(address == 0) \/\/ Depends on environment.<br \/>\nreturn;<\/span><\/p>\n<p>if(detectMemoryLeaksFlag){<br \/>\n\/\/ std::cout &lt;&lt; &#8220;delete[]: &#8221; &lt;&lt; &#8221; address=&#8221; &lt;&lt; address &lt;&lt; std::endl;<br \/>\nstd::map::iterator it = detectMemoryLeaksMemoryMap.begin();<br \/>\nstd::map::iterator itEnd = detectMemoryLeaksMemoryMap.end();<br \/>\nstd::size_t checkAddress = (std::size_t)address;<br \/>\nfor(; it!=itEnd; it++){<br \/>\nif(it-&gt;first == checkAddress){<br \/>\ndetectMemoryLeaksMemoryMap.erase(it);<br \/>\nbreak;<br \/>\n}<br \/>\n}<br \/>\n}<br \/>\nfr<br \/>\nee(address);<br \/>\n}<\/p>\n<p><span style=\"font-size: 0.8em;\">void<br \/>\ndetectMemoryLeaksStart(std::ostream&amp; ros)<br \/>\n{<br \/>\nros &lt;&lt; &#8220;[detect memory leaks] start&#8221; &lt;&lt; std::endl;<br \/>\ndetectMemoryLeaksFlag = true;<br \/>\n}<\/span><\/p>\n<p><span style=\"font-size: 0.8em;\">void<br \/>\ndetectMemoryLeaksEnd(std::ostream&amp; ros)<br \/>\n{<br \/>\nros &lt;&lt; &#8220;[detect memory leaks] end&#8221; &lt;&lt; std::endl;<br \/>\nif(detectMemoryLeaksMemoryMap.size() &gt; 0){<br \/>\nros &lt;&lt; &#8220;memory leaks &#8230;&#8221; &lt;&lt; std::endl;<br \/>\nstd::map::iterator it = detectMemoryLeaksMemoryMap.begin();<br \/>\nstd::map::iterator itEnd = detectMemoryLeaksMemoryMap.end();<br \/>\nfor(; it!=itEnd; it++)<br \/>\nros &lt;&lt; &#8221;&nbsp; &#8221; &lt;&lt; it-&gt;second &lt;&lt; std::endl;<br \/>\n}else{<br \/>\nros &lt;&lt; &#8220;memory leak is nothing.&#8221; &lt;&lt; std::endl;<br \/>\n}<br \/>\ndetectMemoryLeaksFlag = false;<br \/>\ndetectMemoryLeaksMemoryMap.clear();<br \/>\n}<\/span><\/p><\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p>The original article of this in Japanese was written in 2007, so the content may be outdated and unusable. A memory leak occurred in a project that use C++ on Linux. I tried to use&nbsp;MemProf\u3001mtrace\u3001ccmalloc\u3001mpatrol\u3001and dmalloc, but only mtrace was &hellip; <a href=\"https:\/\/blog.tmyymmt.net\/en\/?p=113\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-113","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p2SiSL-1P","_links":{"self":[{"href":"https:\/\/blog.tmyymmt.net\/en\/index.php?rest_route=\/wp\/v2\/posts\/113","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.tmyymmt.net\/en\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.tmyymmt.net\/en\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.tmyymmt.net\/en\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.tmyymmt.net\/en\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=113"}],"version-history":[{"count":12,"href":"https:\/\/blog.tmyymmt.net\/en\/index.php?rest_route=\/wp\/v2\/posts\/113\/revisions"}],"predecessor-version":[{"id":125,"href":"https:\/\/blog.tmyymmt.net\/en\/index.php?rest_route=\/wp\/v2\/posts\/113\/revisions\/125"}],"wp:attachment":[{"href":"https:\/\/blog.tmyymmt.net\/en\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=113"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.tmyymmt.net\/en\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=113"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.tmyymmt.net\/en\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=113"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}