Boost C++ Libraries: Ticket #9248: os_file_functions.hpp: delete_subdirectories_recursive Win32 HANDLE leak https://svn.boost.org/trac10/ticket/9248 <p> I believe there is a memory leak in function delete_subdirectories_recursive in boost\interprocess\detail\os_file_functions.hpp: </p> <div class="wiki-code"><div class="code"><pre><span class="mf">252.</span><span class="kr">inline</span> <span class="kt">bool</span> <span class="n">delete_subdirectories_recursive</span> <span class="mf">253.</span> <span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="o">&amp;</span><span class="n">refcstrRootDirectory</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">dont_delete_this</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">count</span><span class="p">)</span> <span class="mf">254.</span><span class="p">{</span> <span class="mf">255.</span> <span class="kt">bool</span> <span class="n">bSubdirectory</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span> <span class="c1">// Flag, indicating whether</span> <span class="mf">256.</span> <span class="c1">// subdirectories have been found</span> <span class="mf">257.</span> <span class="kt">void</span> <span class="o">*</span> <span class="n">hFile</span><span class="p">;</span> <span class="c1">// Handle to directory</span> <span class="mf">258.</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">strFilePath</span><span class="p">;</span> <span class="c1">// Filepath</span> <span class="mf">259.</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">strPattern</span><span class="p">;</span> <span class="c1">// Pattern</span> <span class="mf">260.</span> <span class="n">winapi</span><span class="o">::</span><span class="n">win32_find_data_t</span> <span class="n">FileInformation</span><span class="p">;</span> <span class="c1">// File information</span> <span class="mf">261.</span> <span class="mf">262.</span> <span class="c1">//Find all files and directories</span> <span class="mf">263.</span> <span class="n">strPattern</span> <span class="o">=</span> <span class="n">refcstrRootDirectory</span> <span class="o">+</span> <span class="s">&quot;</span><span class="se">\\</span><span class="s">*.*&quot;</span><span class="p">;</span> <span class="mf">264.</span> <span class="n">hFile</span> <span class="o">=</span> <span class="n">winapi</span><span class="o">::</span><span class="n">find_first_file</span><span class="p">(</span><span class="n">strPattern</span><span class="p">.</span><span class="n">c_str</span><span class="p">(),</span> <span class="o">&amp;</span><span class="n">FileInformation</span><span class="p">);</span> <span class="mf">265.</span> <span class="k">if</span><span class="p">(</span><span class="n">hFile</span> <span class="o">!=</span> <span class="n">winapi</span><span class="o">::</span><span class="n">invalid_handle_value</span><span class="p">){</span> <span class="mf">266.</span> <span class="k">do</span><span class="p">{</span> <span class="mf">267.</span> <span class="c1">//If it&#39;s not &quot;.&quot; or &quot;..&quot; or the pointed root_level dont_delete_this erase it</span> <span class="mf">268.</span> <span class="k">if</span><span class="p">(</span><span class="n">FileInformation</span><span class="p">.</span><span class="n">cFileName</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39;.&#39;</span> <span class="o">&amp;&amp;</span> <span class="mf">269.</span> <span class="o">!</span><span class="p">(</span><span class="n">dont_delete_this</span> <span class="o">&amp;&amp;</span> <span class="n">count</span> <span class="o">==</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">std</span><span class="o">::</span><span class="n">strcmp</span><span class="p">(</span><span class="n">dont_delete_this</span><span class="p">,</span> <span class="n">FileInformation</span><span class="p">.</span><span class="n">cFileName</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)){</span> <span class="mf">270.</span> <span class="n">strFilePath</span><span class="p">.</span><span class="n">erase</span><span class="p">();</span> <span class="mf">271.</span> <span class="n">strFilePath</span> <span class="o">=</span> <span class="n">refcstrRootDirectory</span> <span class="o">+</span> <span class="s">&quot;</span><span class="se">\\</span><span class="s">&quot;</span> <span class="o">+</span> <span class="n">FileInformation</span><span class="p">.</span><span class="n">cFileName</span><span class="p">;</span> <span class="mf">272.</span> <span class="mf">273.</span> <span class="c1">//If it&#39;s a directory, go recursive</span> <span class="mf">274.</span> <span class="k">if</span><span class="p">(</span><span class="n">FileInformation</span><span class="p">.</span><span class="n">dwFileAttributes</span> <span class="o">&amp;</span> <span class="n">winapi</span><span class="o">::</span><span class="n">file_attribute_directory</span><span class="p">){</span> <span class="mf">275.</span> <span class="c1">// Delete subdirectory</span> <span class="mf">276.</span> <span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">delete_subdirectories_recursive</span><span class="p">(</span><span class="n">strFilePath</span><span class="p">,</span> <span class="n">dont_delete_this</span><span class="p">,</span> <span class="n">count</span><span class="o">+</span><span class="mi">1</span><span class="p">))</span> <span class="mf">277.</span> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span> <span class="mf">278.</span> <span class="p">}</span> <span class="mf">279.</span> <span class="c1">//If it&#39;s a file, just delete it</span> <span class="mf">280.</span> <span class="k">else</span><span class="p">{</span> <span class="mf">281.</span> <span class="c1">// Set file attributes</span> <span class="mf">282.</span> <span class="c1">//if(::SetFileAttributes(strFilePath.c_str(), winapi::file_attribute_normal) == 0)</span> <span class="mf">283.</span> <span class="c1">//return winapi::get_last_error();</span> <span class="mf">284.</span> <span class="c1">// Delete file</span> <span class="mf">285.</span> <span class="n">winapi</span><span class="o">::</span><span class="n">unlink_file</span><span class="p">(</span><span class="n">strFilePath</span><span class="p">.</span><span class="n">c_str</span><span class="p">());</span> <span class="mf">286.</span> <span class="p">}</span> <span class="mf">287.</span> <span class="p">}</span> <span class="mf">288.</span> <span class="c1">//Go to the next file</span> <span class="mf">289.</span> <span class="p">}</span> <span class="k">while</span><span class="p">(</span><span class="n">winapi</span><span class="o">::</span><span class="n">find_next_file</span><span class="p">(</span><span class="n">hFile</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">FileInformation</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">);</span> <span class="mf">290.</span> <span class="mf">291.</span> <span class="c1">// Close handle</span> <span class="mf">292.</span> <span class="n">winapi</span><span class="o">::</span><span class="n">find_close</span><span class="p">(</span><span class="n">hFile</span><span class="p">);</span> <span class="p">...</span> </pre></div></div><p> On line 277, if subsequent call to delete_subdirectories_recursive returns false, the calling function returns also false. But handle hFile (defined on 264) is never closed. I think line winapi::find_close(hFile); before return statement is missing here. </p> <p> I noticed the bug in boost version 1.45.0 and it seems like it's still there in 1.55.0. </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/9248 Trac 1.4.3 tomas.kotal@… Mon, 14 Oct 2013 14:06:20 GMT attachment set https://svn.boost.org/trac10/ticket/9248 https://svn.boost.org/trac10/ticket/9248 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">os_file_functions.patch</span> </li> </ul> <p> Patch </p> Ticket tomas.kotal@… Mon, 14 Oct 2013 14:08:22 GMT component, summary changed; owner set https://svn.boost.org/trac10/ticket/9248#comment:1 https://svn.boost.org/trac10/ticket/9248#comment:1 <ul> <li><strong>owner</strong> set to <span class="trac-author">Ion Gaztañaga</span> </li> <li><strong>component</strong> <span class="trac-field-old">None</span> → <span class="trac-field-new">interprocess</span> </li> <li><strong>summary</strong> <span class="trac-field-old">boost::interprocess - delete_subdirectories_recursive Win32 HANDLE leak</span> → <span class="trac-field-new">os_file_functions.hpp: delete_subdirectories_recursive Win32 HANDLE leak</span> </li> </ul> <p> Please change the component of ticket to interprocess, I was not able to do it in my browser for some reason. Thank you. </p> Ticket Ion Gaztañaga Mon, 14 Oct 2013 19:48:13 GMT <link>https://svn.boost.org/trac10/ticket/9248#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9248#comment:2</guid> <description> <p> You are right, thanks for the bug report. Fortunately the leak shouldn't be common as it's a rare error condition. winapi::find_close(hFile) should do the work. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Ion Gaztañaga</dc:creator> <pubDate>Mon, 14 Oct 2013 19:50:14 GMT</pubDate> <title>status changed; resolution set https://svn.boost.org/trac10/ticket/9248#comment:3 https://svn.boost.org/trac10/ticket/9248#comment:3 <ul> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">fixed</span> </li> </ul> <p> (In <a class="changeset" href="https://svn.boost.org/trac10/changeset/86304" title="Fixes #9248 (&#34;os_file_functions.hpp: delete_subdirectories_recursive ...">[86304]</a>) Fixes <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/9248" title="#9248: Bugs: os_file_functions.hpp: delete_subdirectories_recursive Win32 HANDLE leak (closed: fixed)">#9248</a> ("os_file_functions.hpp: delete_subdirectories_recursive Win32 HANDLE leak") </p> Ticket