{"id":1166,"date":"2011-03-04T22:13:28","date_gmt":"2011-03-04T20:13:28","guid":{"rendered":"https:\/\/alax.info\/blog\/?p=1166"},"modified":"2011-03-04T22:13:28","modified_gmt":"2011-03-04T20:13:28","slug":"atl-activex-control-hosting-memory-leak-_freea-assertion-failure-and-more","status":"publish","type":"post","link":"https:\/\/alax.info\/blog\/1166","title":{"rendered":"ATL ActiveX control hosting memory leak, _freea assertion failure and more"},"content":{"rendered":"<p>If you were adding and removing ActiveX controls programmatically with ATL, you might have noticed a nasty memory leak after final release of the control. Control added, removed and a leaky block is left om heap.<\/p>\n<p>Tracking simple memory leaks is not a rocket science with Microsoft C++ runtime, by adding _CRTDBG_MAP_ALLOC define, as described in <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/e5ewb1h3.aspx\">Memory Leak Detection Enabling on MSDN<\/a>:<\/p>\n<pre><span style=\"color: blue;\">#if<\/span> defined(_DEBUG)\r\n<span style=\"color: blue;\">#define<\/span> _CRTDBG_MAP_ALLOC\r\n#<span style=\"color: blue;\">include<\/span> &lt;stdlib.h&gt;\r\n#<span style=\"color: blue;\">include<\/span> &lt;crtdbg.h&gt;\r\n<span style=\"color: blue;\">#endif<\/span> <span style=\"color: green;\">\/\/ defined(_DEBUG)<\/span><\/pre>\n<p>Having that done, the problem was isolated to an extra instance of CAxHostWindow, which was excessively instantiated and never freed. Luckily, having this done you already have sufficient amount of keywords on hands to locate relevant articles on Microsoft knowledge base:<\/p>\n<ul>\n<li><a href=\"http:\/\/support.microsoft.com\/KB\/229904\">PRB: CAxWindow Members Can Cause a Memory Leak<\/a><\/li>\n<li><a href=\"How to add ActiveX controls to an ATL composite control programmatically in Visual C++\">How to add ActiveX controls to an ATL composite control programmatically in Visual C++<\/a><\/li>\n<\/ul>\n<p>Basically, what is taking place is the behavior by design. That is, AtlAxCreateControlEx API is leaky by design, one gotta just be aware.<\/p>\n<pre>CComPtr&lt;IUnknown&gt; pContainerUnkonwn, pControlUnknown;\r\n<span style=\"color: blue;\">static<\/span> LPCTSTR g_pszControlClass = _T(<span style=\"color: maroon;\">\"{8856F961-340A-11D0-A96B-00C04FD705A2}\"<\/span>);\r\n<span style=\"color: green;\">\/\/ NOTE: This results in two instances of CAxWindowHost being created, one of which appears to be leaked (see below), <\/span>\r\n<span style=\"color: green;\">\/\/       see http:\/\/support.microsoft.com\/kb\/218442<\/span>\r\n<span style=\"color: green;\">\/\/ <\/span>\r\n<span style=\"color: green;\">\/\/ Detected memory leaks!<\/span>\r\n<span style=\"color: green;\">\/\/ Dumping objects -&gt;<\/span>\r\n<span style=\"color: green;\">\/\/ {81} normal block at 0x00128928, 244 bytes long.<\/span>\r\n<span style=\"color: green;\">\/\/ Data: &lt;x .       .     &gt; 78 09 2E 01 01 00 00 00 0C 10 2E 01 00 00 00 00 <\/span>\r\n<span style=\"color: green;\">\/\/ Object dump complete.<\/span>\r\nATLENSURE_SUCCEEDED(AtlAxCreateControlEx(CT2COLE(g_pszControlClass), m_hWnd, <span style=\"color: blue;\">NULL<\/span>, &amp;pContainerUnkonwn, &amp;pControlUnknown));<\/pre>\n<p><!--more-->A workaround here is suggested by Q218442 and is a replacement of AtlAx* API call with a CAxWindow class:<\/p>\n<pre>CComPtr&lt;IUnknown&gt; pContainerUnkonwn, pControlUnknown;\r\n<span style=\"color: blue;\">static<\/span> LPCTSTR g_pszControlClass = _T(<span style=\"color: maroon;\">\"{8856F961-340A-11D0-A96B-00C04FD705A2}\"<\/span>);\r\nCAxWindow AxWindow;\r\nAxWindow.Attach(m_hWnd);\r\nATLENSURE_SUCCEEDED(AxWindow.CreateControlEx(CT2COLE(g_pszControlClass), <span style=\"color: blue;\">NULL<\/span>, &amp;pContainerUnkonwn, &amp;pControlUnknown));<\/pre>\n<p>The happiness of leak resolution here might be somewhat diluted by a weird assertion failure coming out from the deepness of ATL. The problem comes from ~CAutoStackPtr destructor (undocumented) trying to <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/k8984a8h.aspx\">_freea<\/a> a memory block allocated by caller&#8217;s <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/5471dc8s.aspx\">_malloca<\/a>. While caller&#8217;s _malloca is converted to plain heap allocation (_malloc_dbg) for debugging purposes, _freea is still looking for security cookie which never existed. Hence, assertion failure:<\/p>\n<pre>_ASSERTE((<span style=\"color: maroon;\">\"Corrupted pointer passed to _freea\"<\/span>, <span style=\"color: maroon;\">0<\/span>));<\/pre>\n<p>Unfortunately, it appears that _CRTDBG_MAP_ALLOC macro is not compatible with _malloca\/_freea, the problem exists in versions of Visual C++ 2008 (at least) through 2010 SP1.<\/p>\n<p>Vote for the problem on MS Connect: <a href=\"https:\/\/connect.microsoft.com\/VisualStudio\/feedback\/details\/649364\/malloca-freea-mismatch-with-malloc-debug-builds-crtdbg-map-alloc\">_malloca\/_freea mismatch with malloc debug builds (_CRTDBG_MAP_ALLOC)<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>If you were adding and removing ActiveX controls programmatically with ATL, you might have noticed a nasty memory leak after final release of the control. Control added, removed and a leaky block is left om heap. Tracking simple memory leaks is not a rocket science with Microsoft C++ runtime, by adding _CRTDBG_MAP_ALLOC define, as described&hellip; <\/p>\n<p><a class=\"moretag\" href=\"https:\/\/alax.info\/blog\/1166\">Read the full article<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11],"tags":[487,63,38,59],"class_list":["post-1166","post","type-post","status-publish","format-standard","hentry","category-atl","tag-atl","tag-bug","tag-c","tag-microsoft"],"_links":{"self":[{"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/posts\/1166","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/comments?post=1166"}],"version-history":[{"count":0,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/posts\/1166\/revisions"}],"wp:attachment":[{"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/media?parent=1166"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/categories?post=1166"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/tags?post=1166"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}