{"id":95397,"date":"2017-02-09T07:00:00","date_gmt":"2017-02-09T22:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/?p=95397"},"modified":"2019-03-13T01:05:48","modified_gmt":"2019-03-13T08:05:48","slug":"20170209-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20170209-00\/?p=95397","title":{"rendered":"Suspicious memory leak in std::basic_string"},"content":{"rendered":"<p>A customer asked for assistance debugging a memory leak. Their memory leak detection tool was reporting a leak in the following call stack: <\/p>\n<pre>\nntdll!RtlAllocateHeap\nContoso!malloc\nContoso!Allocator&lt;unsigned short&gt;::allocate\nContoso!std::basic_string&lt;unsigned short,std::char_traits&lt;unsigned short&gt;,Allocator&lt;unsigned short&gt;,_STL70&gt;::_Copy\nContoso!std::basic_string&lt;unsigned short,std::char_traits&lt;unsigned short&gt;,Allocator&lt;unsigned short&gt;,_STL70&gt;::_Grow\nContoso!std::basic_string&lt;unsigned short,std::char_traits&lt;unsigned short&gt;,Allocator&lt;unsigned short&gt;,_STL70&gt;::assign\nContoso!std::basic_string&lt;unsigned short,std::char_traits&lt;unsigned short&gt;,Allocator&lt;unsigned short&gt;,_STL70&gt;::assign\nContoso!std::basic_string&lt;unsigned short,std::char_traits&lt;unsigned short&gt;,Allocator&lt;unsigned short&gt;,_STL70&gt;::operator=\nContoso!ConfigurationImpl::validate\n<\/pre>\n<p>&#8220;The <code>Configuration&shy;Impl<\/code> object itself is not being leaked. Just the string inside it.&#8221; <\/p>\n<p>The Visual C++ team reported that there are no known memory leaks in STL70. However, the code above is using a custom allocator, so they asked to see more of the customer&#8217;s code. <\/p>\n<p>And they found the smoking gun, but it wasn&#8217;t in the allocator. It was in the class constructor. <\/p>\n<pre>\nConfigurationImpl::ConfigurationImpl()\n{\n    \/\/ Initialize all members to zero.\n    memset(this, 0, sizeof(ConfigurationImpl));\n}\n<\/pre>\n<p><code>basic_string<\/code>, like all STL objects, is non-POD. A POD type is roughly&sup1; something that can be declared in C as a plain old <code>struct<\/code>, such as <code>struct Pod { int x; int y; };<\/code>. POD types can be treated as a blob of bytes that you can manipulate with <code>memset<\/code>, <code>memcpy<\/code>, and such. Non-POD types, on the other hand, are those with things like constructors, destructors, virtual methods, all that fancy C++ stuff. You cannot treat them as just a blob of bytes because they have other fancy behaviors attached, and treating them as a blob of bytes bypasses (and may even damage) those fancy behaviors. <\/p>\n<p>In this case, using <code>memset<\/code> to zero out a <code>basic_string<\/code> wipes out all the work that was performed by the <code>basic_string<\/code> constructor and results in the dreaded <i>undefined behavior<\/i>. Maybe undefined behavior manifests itself as a memory leak. Maybe it manifests itself as a crash. Maybe it manifests itself as <a HREF=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/\">time travel<\/a>. <\/p>\n<p>In practical terms, what you have there is memory corruption. When you have memory corruption, crazy things can happen. So don&#8217;t corrupt memory. <\/p>\n<p>The customer thanked us for our assistance and fixed their code. <\/p>\n<p>&sup1;This is a simplified discussion, so don&#8217;t haul out your language-lawyer pitchforks. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>There are not the PODs you are looking for.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-95397","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>There are not the PODs you are looking for.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/95397","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=95397"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/95397\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=95397"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=95397"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=95397"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}