<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://shuye.dev/blog</id>
    <title>Ye Shu Blog</title>
    <updated>2021-08-13T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://shuye.dev/blog"/>
    <subtitle>Ye Shu Blog</subtitle>
    <icon>https://shuye.dev/favicon.ico</icon>
    <entry>
        <title type="html"><![CDATA[Memory Leak & malloc chunks]]></title>
        <id>https://shuye.dev/blog/malloc_chunk</id>
        <link href="https://shuye.dev/blog/malloc_chunk"/>
        <updated>2021-08-13T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[How it all started]]></summary>
        <content type="html"><![CDATA[<h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-it-all-started">How it all started<a href="https://shuye.dev/blog/malloc_chunk#how-it-all-started" class="hash-link" aria-label="Direct link to How it all started" title="Direct link to How it all started">​</a></h2>
<p>While debugging a memory leak bug during my summer internship, I found out that one of our APIs returned a raw pointer and thus transferred its ownership to the caller (me). In other words, I'm now responsible of <code>delete</code>-ing the pointer after my code finishes. While this is <a href="https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#i11-never-transfer-ownership-by-a-raw-pointer-t-or-reference-t" target="_blank" rel="noopener noreferrer">a terrible engineering practice</a>, I grew interested in how memory leaks happen, and how <code>delete[]</code> solves the problem.</p>
<p>After some research &amp; experiments, I wrote this blog post, which hopefully addresses three sets of questions</p>
<ol>
<li>What are memory leaks?</li>
<li>How are objects allocated on the heap? How does <code>delete[]</code> know which area of memory to be freed?</li>
<li>How can we prevent memory leaks from happening?</li>
</ol>
<p>While the Stack Overflow question <a href="https://stackoverflow.com/questions/197675/how-does-delete-know-the-size-of-the-operand-array" target="_blank" rel="noopener noreferrer">"How does delete[] 'know' the size of the operand array?"</a> sort of answers the second question, I decide to dig deeper into the actual memory area.</p>
<p>Coincidentally, I have worked on a heap exploitation problem with my friend <a href="https://guozhen.dev/" target="_blank" rel="noopener noreferrer">@gzhding</a> in a past CTF event. Thanks to the experience, I learned how to use <code>gdb</code> to dump the heap memory and gain some insight into the problem.</p>
<!-- -->
<div class="tocCollapsible_ETCw"><button type="button" class="clean-btn tocCollapsibleButton_TO0P">On this page</button></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-are-memory-leaks">What are Memory Leaks?<a href="https://shuye.dev/blog/malloc_chunk#what-are-memory-leaks" class="hash-link" aria-label="Direct link to What are Memory Leaks?" title="Direct link to What are Memory Leaks?">​</a></h2>
<p>We know that <a href="https://www.cplusplus.com/doc/tutorial/dynamic/" target="_blank" rel="noopener noreferrer">C++ can dynamically allocate memory on the heap</a>. A common example is to use <code>new[]</code> to create an array and <code>delete[]</code> to remove it.</p>
<p><a href="https://en.wikipedia.org/wiki/Memory_leak" target="_blank" rel="noopener noreferrer">Memory leaks</a> happens when we create an array in the memory (<em>i.e.</em> "allocates" a segment of memory to store the object) and forget to delete it. When the pointer to the memory goes out of scope, the running code becomes ignorant of the allocated memory area. In worst cases, when the leakage happens in a loop, newly allocated memory will continue to pile up without being released, potentially slowing down or crash the computer.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="poc">PoC<a href="https://shuye.dev/blog/malloc_chunk#poc" class="hash-link" aria-label="Direct link to PoC" title="Direct link to PoC">​</a></h3>
<p>Here is a short Proof of Concept (PoC) code. The <code>main()</code> function calls the <code>memory_leak()</code> function, which allocates an array of 26 <code>char</code>s and fills them with capital English alphabets.</p>
<div class="language-cpp codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Ktv7">memory_leak.cpp</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-cpp codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">memory_leak</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Always delete pointers created by new to avoid memory leaks!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">char</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token plain">arr </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">char</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">26</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">26</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> i</span><span class="token operator" style="color:#393A34">++</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        arr</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">i</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">char</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">65</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> i</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 65 is the ascii of 'A'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// The memory area is not freed!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// delete[] arr;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">memory_leak</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>As the <code>delete[]</code> statement is commented out, when the function <code>memory_leak()</code> returns, the pointer <code>arr</code> goes out of scope and results in the memory area leaked.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="a-deeper-look-into-the-memory">A Deeper Look into the Memory<a href="https://shuye.dev/blog/malloc_chunk#a-deeper-look-into-the-memory" class="hash-link" aria-label="Direct link to A Deeper Look into the Memory" title="Direct link to A Deeper Look into the Memory">​</a></h3>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>note</div><div class="admonitionContent_BuS1"><p>Instead of native GDB, I use <a href="https://github.com/hugsy/gef" target="_blank" rel="noopener noreferrer">GEF</a> (GDB Enhanced Features) for prettified output and some extra features like <code>heap</code>.</p></div></div>
<p>Let us compile the program with <code>g++ -g3 memory_leak.cpp -o memory_leak</code> (the <code>-g3</code> flag preserves debug information during compilation) and use <code>gdb</code> to verify the memory leak.</p>
<p>We'll add a breakpoint at the end of function <code>memory_leak()</code> and run the program until it hits the breakpoint.</p>
<div class="language-console codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-console codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">$ gdb memory_leak</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">gef➤  b 11</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Breakpoint 1 at 0x1179: file memory_leak.cpp, line 11.</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">gef➤  r</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">[...]</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">─────────────────────────────────────────────────────────────── source:memory_leak.cpp+11 ────</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      6          arr[i] = char(65 + i); // 65 is the ascii of 'A'</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      7      }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      8</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      9      // The memory area is not freed!</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     10      // delete[] arr;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">●→   11  }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     12</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     13  int main() {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     14      memory_leak();</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     15      return 0;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     16  }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">───────────────────────────────────────────────────────────────────────────────── threads ────</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">[#0] Id 1, Name: "memory_leak", stopped 0x555555555179 in memory_leak (), reason: BREAKPOINT</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">─────────────────────────────────────────────────────────────────────────────────── trace ────</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">[#0] 0x555555555179 → memory_leak()</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">[#1] 0x555555555186 → main()</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">──────────────────────────────────────────────────────────────────────────────────────────────</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">gef➤  info locals</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">arr = 0x55555556aeb0 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">gef➤  x/8xw 0x55555556aeb0</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">0x55555556aeb0: 0x44434241      0x48474645      0x4c4b4a49      0x504f4e4d</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">0x55555556aec0: 0x54535251      0x58575655      0x00005a59      0x00000000</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>After the program hits the breakpoint, we print out the address of pointer <code>arr</code> and the content of that memory. Note that the memory is stored in <a href="https://en.wikipedia.org/wiki/Little-endian" target="_blank" rel="noopener noreferrer">little endian</a> order, so <code>0x44</code> (D) comes before <code>0x43</code> (C), <code>0x42</code> (B), and finally <code>0x41</code> (A).</p>
<p>Now, let us continue running the program until <code>memory_leak()</code> returns back to <code>main()</code>.</p>
<div class="language-gdb codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-gdb codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">gef➤  finish</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">[...]</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">─────────────────────────────────────────────────────────────── source:memory_leak.cpp+15 ────</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     10      // delete[] arr;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">●    11  }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     12</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     13  int main() {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     14      memory_leak();</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> →   15      return 0;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     16  }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">───────────────────────────────────────────────────────────────────────────────── threads ────</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">[#0] Id 1, Name: "memory_leak", stopped 0x555555555186 in main (), reason: TEMPORARY BREAKPOINT</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">─────────────────────────────────────────────────────────────────────────────────── trace ────</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">[#0] 0x555555555186 → main()</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">──────────────────────────────────────────────────────────────────────────────────────────────</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">gef➤  info locals</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">No locals.</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">gef➤  x/8xw 0x55555556aeb0</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">0x55555556aeb0: 0x44434241      0x48474645      0x4c4b4a49      0x504f4e4d</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">0x55555556aec0: 0x54535251      0x58575655      0x00005a59      0x00000000</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Now that <code>memory_leak()</code> returns, we have lost the pointer <code>arr</code> pointing to the memory address <code>0x55555556aeb0</code>. However, as we print out the memory area, the data is still stored in the memory without being released, leading to a memory leak.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="verification-with-valgrind">Verification with Valgrind<a href="https://shuye.dev/blog/malloc_chunk#verification-with-valgrind" class="hash-link" aria-label="Direct link to Verification with Valgrind" title="Direct link to Verification with Valgrind">​</a></h3>
<p>Furthermore, we can use automated tools like <a href="https://valgrind.org/" target="_blank" rel="noopener noreferrer">Valgrind</a> to check for memory leaks.</p>
<div class="language-console codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-console codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">$ valgrind --leak-check=full ./memory_leak</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">==382643== Memcheck, a memory error detector</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">==382643== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">==382643== Using Valgrind-3.17.0 and LibVEX; rerun with -h for copyright info</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">==382643== Command: ./memory_leak</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">==382643==</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">==382643==</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">==382643== HEAP SUMMARY:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">==382643==     in use at exit: 26 bytes in 1 blocks</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">==382643==   total heap usage: 2 allocs, 1 frees, 72,730 bytes allocated</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">==382643==</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">==382643== 26 bytes in 1 blocks are definitely lost in loss record 1 of 1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">==382643==    at 0x484021F: operator new[](unsigned long) (vg_replace_malloc.c:579)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">==382643==    by 0x10914A: memory_leak() (memory_leak.cpp:3)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">==382643==    by 0x109185: main (memory_leak.cpp:14)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">==382643==</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">==382643== LEAK SUMMARY:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">==382643==    definitely lost: 26 bytes in 1 blocks</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">==382643==    indirectly lost: 0 bytes in 0 blocks</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">==382643==      possibly lost: 0 bytes in 0 blocks</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">==382643==    still reachable: 0 bytes in 0 blocks</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">==382643==         suppressed: 0 bytes in 0 blocks</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">==382643==</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">==382643== For lists of detected and suppressed errors, rerun with: -s</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">==382643== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-are-objects-allocated-on-the-heap">How are objects allocated on the heap?<a href="https://shuye.dev/blog/malloc_chunk#how-are-objects-allocated-on-the-heap" class="hash-link" aria-label="Direct link to How are objects allocated on the heap?" title="Direct link to How are objects allocated on the heap?">​</a></h2>
<p>To understand better the mechanisms behind memory leaks, we need to know how C++ allocates and frees memories, <em>i.e.</em> how <code>new</code> and <code>delete</code> works. Let us dig deeper into the source code of GNU's <code>libstdc++</code> implementation (the library used by g++ by default).</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-new-and-delete-works">How <code>new</code> and <code>delete</code> works<a href="https://shuye.dev/blog/malloc_chunk#how-new-and-delete-works" class="hash-link" aria-label="Direct link to how-new-and-delete-works" title="Direct link to how-new-and-delete-works">​</a></h3>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>As <code>new</code> and <code>delete</code> operators are merely interfaces defined by the C++ standard and have different implementations, here I'll use the <a href="https://github.com/gcc-mirror/gcc/tree/releases/gcc-11.2.0" target="_blank" rel="noopener noreferrer">source code</a> of GNU's <code>libstdc++</code> that ships with gcc version 11.2.0 for reference.</p></div></div>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="new-and-delete-are-just-wrappers-of-new-and-delete"><code>new[]</code> and <code>delete[]</code> are just wrappers of <code>new</code> and <code>delete</code><a href="https://shuye.dev/blog/malloc_chunk#new-and-delete-are-just-wrappers-of-new-and-delete" class="hash-link" aria-label="Direct link to new-and-delete-are-just-wrappers-of-new-and-delete" title="Direct link to new-and-delete-are-just-wrappers-of-new-and-delete">​</a></h4>
<p>Interestingly, from the implementation of <code>operator new[]</code> (<a href="https://github.com/gcc-mirror/gcc/blob/releases/gcc-11.2.0/libstdc++-v3/libsupc++/new_opv.cc#L29-L33" target="_blank" rel="noopener noreferrer">source</a>), it seems that in <code>stdlibc++</code>, <code>new[]</code> is just an alias for <code>new</code>.</p>
<div class="language-cpp codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Ktv7">/libstdc++-v3/libsupc++/new_opv.cc:L29-33</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-cpp codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">_GLIBCXX_WEAK_DEFINITION </span><span class="token keyword" style="color:#00009f">void</span><span class="token operator" style="color:#393A34">*</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">operator</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">std</span><span class="token double-colon punctuation" style="color:#393A34">::</span><span class="token plain">size_t sz</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">_GLIBCXX_THROW</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">std</span><span class="token double-colon punctuation" style="color:#393A34">::</span><span class="token plain">bad_alloc</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token double-colon punctuation" style="color:#393A34">::</span><span class="token keyword" style="color:#00009f">operator</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">sz</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The same is true for <code>delete[]</code> (<a href="https://github.com/gcc-mirror/gcc/blob/releases/gcc-11.2.0/libstdc++-v3/libsupc++/del_opv.cc#L32-L36" target="_blank" rel="noopener noreferrer">source</a>), which is just an alias for <code>delete</code>.</p>
<div class="theme-admonition theme-admonition-caution admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>caution</div><div class="admonitionContent_BuS1"><p>From the implementation of GNU stdlibc++, it seems perfectly ok to mix the use of <code>new[]</code> with <code>new</code>, and <code>delete[]</code> with <code>delete</code>.</p><p>However, you should never do this, because this behavior is implementation-specific. Using <code>new</code> and <code>delete</code> instead of <code>new[]</code> and <code>delete[]</code> leads to undefined behavior (according to <a href="https://timsong-cpp.github.io/cppwp/expr.delete#2" target="_blank" rel="noopener noreferrer">C++ Working Paper</a>) and will make your life painful.</p></div></div>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="and-new--delete-are-wrappers-of-malloc-and-free">And <code>new</code> &amp; <code>delete</code> are wrappers of <code>malloc</code> and <code>free</code><a href="https://shuye.dev/blog/malloc_chunk#and-new--delete-are-wrappers-of-malloc-and-free" class="hash-link" aria-label="Direct link to and-new--delete-are-wrappers-of-malloc-and-free" title="Direct link to and-new--delete-are-wrappers-of-malloc-and-free">​</a></h4>
<p>Now let us take a look at the <a href="https://github.com/gcc-mirror/gcc/blob/releases/gcc-11.2.0/libstdc++-v3/libsupc++/new_op.cc#L41-L59" target="_blank" rel="noopener noreferrer">source code</a> of <code>new</code>. It's just a wrapper around C's <code>malloc</code> plus some error handling and returns the <code>malloc</code>-ed raw pointer to the caller.</p>
<div class="language-cpp codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Ktv7">/libstdc++-v3/libsupc++/new_op.cc:L41-59</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-cpp codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">_GLIBCXX_WEAK_DEFINITION </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">operator</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">std</span><span class="token double-colon punctuation" style="color:#393A34">::</span><span class="token plain">size_t sz</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">_GLIBCXX_THROW</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">std</span><span class="token double-colon punctuation" style="color:#393A34">::</span><span class="token plain">bad_alloc</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token plain">p</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">/* malloc (0) is unpredictable; avoid it.  */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">__builtin_expect</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">sz </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">false</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    sz </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">while</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">p </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">malloc</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">sz</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      new_handler handler </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> std</span><span class="token double-colon punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">get_new_handler</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token plain"> handler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">_GLIBCXX_THROW_OR_ABORT</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">bad_alloc</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token function" style="color:#d73a49">handler</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> p</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><code>delete</code> (<a href="https://github.com/gcc-mirror/gcc/blob/releases/gcc-11.2.0/libstdc++-v3/libsupc++/del_op.cc#L46-L50" target="_blank" rel="noopener noreferrer">source</a>) is even simpler, and just calls C's <code>free</code>.</p>
<div class="language-cpp codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Ktv7">libstdc++-v3/libsupc++/del_op.cc:L46-50</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-cpp codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">_GLIBCXX_WEAK_DEFINITION </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">operator</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">delete</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">void</span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> ptr</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">noexcept</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  std</span><span class="token double-colon punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">free</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ptr</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Hence it seems that we should dive all the way into C standard library's implementation of <code>malloc</code> and <code>free</code> and see what exactly is happening behind the creation and deletion of arrays.</p>
<p>However, instead of covering the full picture of <code>malloc</code> (which could fill another blog post), we'll be mainly focusing on how <code>malloc</code> structures the allocated memory area (answer: using <code>malloc_chunk</code>s on the heap) and how <code>free</code> knows which area of memory to be released.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-are-malloc_chunks-structured">How are <code>malloc_chunk</code>s structured?<a href="https://shuye.dev/blog/malloc_chunk#how-are-malloc_chunks-structured" class="hash-link" aria-label="Direct link to how-are-malloc_chunks-structured" title="Direct link to how-are-malloc_chunks-structured">​</a></h3>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>Like in the previous section, I will use GNU's implementation of C standard library, <em>i.e.</em> <code>glibc</code>.
The current version is <a href="https://sourceware.org/git/?p=glibc.git;a=tag;h=refs/tags/glibc-2.34" target="_blank" rel="noopener noreferrer">glibc 2.34</a>, which is released on Aug 2, 2021.</p></div></div>
<p>The following content comes from the comments in <code>malloc/malloc.c</code> of glibc (<a href="https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=e065785af77af72c17c773517c15b248b067b4ad;hb=ae37d06c7d127817ba43850f0f898b793d42aea7#l1168" target="_blank" rel="noopener noreferrer">source</a>). I've done some minor edits to adapt the format to Markdown (what this website uses).</p>
<blockquote>
<p>(The following includes lightly edited explanations by Colin Plumb.)</p>
<p>Chunks of memory are maintained using a `boundary tag' method as
described in e.g., Knuth or Standish. (See the paper by Paul
Wilson <a href="ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps" target="_blank" rel="noopener noreferrer">ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps</a> for a
survey of such techniques.) Sizes of free chunks are stored both
in the front of each chunk and at the end. This makes
consolidating fragmented chunks into bigger chunks very fast. The
size fields also hold bits representing whether chunks are free or
in use.</p>
<p>An allocated chunk looks like this:</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    chunk-&gt; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            |             Size of previous chunk, if unallocated (P clear)  |</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            |             Size of chunk, in bytes                     |A|M|P|</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      mem-&gt; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            |             User data starts here...                          .</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            .                                                               .</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            .             (malloc_usable_size() bytes)                      .</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            .                                                               |</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">nextchunk-&gt; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            |             (size of chunk, but used for application data)    |</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            |             Size of next chunk, in bytes                |A|0|1|</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Where "chunk" is the front of the chunk for the purpose of most of
the malloc code, but "mem" is the pointer that is returned to the
user. "Nextchunk" is the beginning of the next contiguous chunk.</p>
<p>Chunks always begin on even word boundaries, so the mem portion
(which is returned to the user) is also on an even word boundary, and
thus at least double-word aligned.</p>
<p>Free chunks are stored in circular doubly-linked lists, and look like this:</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    chunk-&gt; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            |             Size of previous chunk, if unallocated (P clear)  |</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    `head:' |             Size of chunk, in bytes                     |A|0|P|</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      mem-&gt; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            |             Forward pointer to next chunk in list             |</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            |             Back pointer to previous chunk in list            |</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            |             Unused space (may be 0 bytes long)                .</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            .                                                               .</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            .                                                               |</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">nextchunk-&gt; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    `foot:' |             Size of chunk, in bytes                           |</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            |             Size of next chunk, in bytes                |A|0|0|</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The P (<code>PREV_INUSE</code>) bit, stored in the unused low-order bit of the
chunk size (which is always a multiple of two words), is an in-use
bit for the <em>previous</em> chunk. If that bit is <em>clear</em>, then the
word before the current chunk size contains the previous chunk
size, and can be used to find the front of the previous chunk.
The very first chunk allocated always has this bit set,
preventing access to non-existent (or non-owned) memory. If
<code>prev_inuse</code> is set for any given chunk, then you CANNOT determine
the size of the previous chunk, and might even get a memory
addressing fault when trying to do so.</p>
<p>[...]</p>
<p>Note that the <code>foot</code> of the current chunk is actually represented
as the <code>prev_size</code> of the NEXT chunk. This makes it easier to
deal with alignments etc but can be very confusing when trying
to extend or adapt this code.</p>
<p>[...]</p>
</blockquote>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="a-verification-using-poc">A verification using PoC<a href="https://shuye.dev/blog/malloc_chunk#a-verification-using-poc" class="hash-link" aria-label="Direct link to A verification using PoC" title="Direct link to A verification using PoC">​</a></h3>
<p>Now we can use <code>gdb</code> to actually print out the memory area and see how the explanation above applies to our case. Here I used the <code>heap</code> feature introduced by <a href="https://gef.readthedocs.io/en/master/commands/heap/#heap-chunk-command" target="_blank" rel="noopener noreferrer">GEF</a> to better visualize the <code>malloc</code>-ed chunk's properties.</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">gef➤  heap chunk arr</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Chunk(addr=0x55555556aeb0, size=0x30, flags=PREV_INUSE)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Chunk size: 48 (0x30)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Usable size: 40 (0x28)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Previous chunk size: 0 (0x0)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">PREV_INUSE flag: On</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">IS_MMAPPED flag: Off</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">NON_MAIN_ARENA flag: Off</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">gef➤  x/16xw 0x55555556aeb0-16</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">0x55555556aea0:	0x00000000	0x00000000	0x00000031	0x00000000</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">0x55555556aeb0:	0x44434241	0x48474645	0x4c4b4a49	0x504f4e4d</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">0x55555556aec0:	0x54535251	0x58575655	0x00005a59	0x00000000</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">0x55555556aed0:	0x00000000	0x00000000	0x0000f131	0x00000000</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Note that here the chunk size is 48 bytes, with the usable size (size of actual user memory area) being 40, which is much higher than what we requested (an array of 26 chars, which should be 26 bytes). This is because "chunks always begin on even word boundaries ... and thus at least double-word aligned." (from the blockquote above).</p>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>The size of a <a href="https://en.wikipedia.org/wiki/Word_(computer_architecture)" target="_blank" rel="noopener noreferrer">word</a> varies by architecture. For a normal 64 bit system, the word is 64 bit long and thus takes up 8 bytes in size. However, a word in <code>gdb</code> <code>x/w</code> command has a fixed length of 32 bits (4 bytes), which is a bit confusing. Hence, I'll use "word" to refer to an actual variable-size word, and "32-bit word" to refer to the <code>gdb</code> word.</p></div></div>
<p>Since the chunk in memory is always double-word aligned, we should minus the address by <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>2</mn><mo>×</mo><mn>8</mn><mo>=</mo><mn>16</mn></mrow><annotation encoding="application/x-tex">2\times8=16</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em"></span><span class="mord">2</span><span class="mspace" style="margin-right:0.2222em"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em"></span></span><span class="base"><span class="strut" style="height:0.6444em"></span><span class="mord">8</span><span class="mspace" style="margin-right:0.2778em"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em"></span></span><span class="base"><span class="strut" style="height:0.6444em"></span><span class="mord">16</span></span></span></span> bytes to obtain the <code>chunk</code> pointer address. Here the first word (represented by 2 32-bit words as in gdb) is filled with <code>0x00</code>, and will be filled with the area of the previous chunk, if the <code>P</code> flag in unset.</p>
<p>The second word <code>0x31</code> (or <code>0b110001</code>) stores the chunk size and 3 flags. The least significant bit <code>0b1</code> indicates that the flag <code>P</code> (PREV_INUSE) is set, so the previous chunk has not been freed. Since all chunks must have size at least of multiples of 8, the 3 least significant bits of the size field is always 0, which is why the 3 LSBs can be used as flags. To calculate the chunk size, we can discard the 3 LSBs and obtain <code>0b110000</code> (<code>0x30</code>, or 48) bytes.</p>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>note</div><div class="admonitionContent_BuS1"><p>If you are cautious enough, you might have noticed that the usable size for the chunk is 40, which is only 8 bytes (not 16), <em>i.e.</em> one word, less than the chunk size.</p><p>This is because the <code>chunk</code> pointer <a href="https://sourceware.org/glibc/wiki/MallocInternals#What_is_a_Chunk.3F" target="_blank" rel="noopener noreferrer">"does not point to the beginning of the chunk, but to the last word in the previous chunk"</a>. The actual chunk starts at the next word of <code>chunk</code> pointer (which stores the sizes).</p></div></div>
<p>So, our "actual" chunk starts at the address <code>0x55555556aea8</code> and ends at <code>0x55555556aec8</code>. The data area starts from <code>0x55555556aeb0</code> and ends in <code>0x55555556aec8</code>. Similarly, the next <code>chunk</code> pointer points to the last word in our chunk's data area (<code>0x55555556aec8</code>).</p>
<p>Then, why does the chunk pointer confusingly points to the last word in the previous chunk? The answer is related to the <code>free</code> design mechanism.</p>
<p>Because when the previous chunk is freed, it'll fill its last word with its size and clear the <code>P</code> flag in its next chunk (ours). Hence, our chunk can use this size "to find the front of the previous chunk" after the previous chunk has been freed.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-does-free-work">How does <code>free</code> work?<a href="https://shuye.dev/blog/malloc_chunk#how-does-free-work" class="hash-link" aria-label="Direct link to how-does-free-work" title="Direct link to how-does-free-work">​</a></h3>
<p>By now, you should already have the answer to "how does <code>delete[]</code> know which area of memory to be freed"—because the size of the chunk is stored in its metadata.</p>
<p>However, there are still some intricacies to be solved: why does the chunk pointer points to the last word in the previous chunk? Why do we need the <code>PREV_INUSE</code> (P) flag? To do so, we shall look into how <code>free</code> works.</p>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>note</div><div class="admonitionContent_BuS1"><p>While reading this section, you can refer back to the section <a href="https://shuye.dev/blog/malloc_chunk#how-are-malloc_chunks-structured">How are malloc_chunks structured?
</a> to see how memory chunks look like before and after <code>free</code>.</p></div></div>
<p>Long story short, <code>free</code> works like the following. When it is called (<a href="https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=e065785af77af72c17c773517c15b248b067b4ad;hb=ae37d06c7d127817ba43850f0f898b793d42aea7#l3237" target="_blank" rel="noopener noreferrer">source</a>), the user would pass a pointer to the memory area to it, <code>free</code> would then call <code>mem2chunk</code> (<a href="https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=e065785af77af72c17c773517c15b248b067b4ad;hb=ae37d06c7d127817ba43850f0f898b793d42aea7#l1310" target="_blank" rel="noopener noreferrer">source</a>) to convert the pointer to point to the chunk header. Then, if the chunk is allocated by <code>mmap</code> indicated by the M flag, <code>free</code> calls <code>munmap</code> (<a href="https://man.archlinux.org/man/munmap.3p.en" target="_blank" rel="noopener noreferrer">man 3p</a> | <a href="https://man.archlinux.org/man/munmap.2.en" target="_blank" rel="noopener noreferrer">man 2</a>) to release the chunk; if not, it passes the chunk pointer to <code>_int_free</code> (<a href="https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=e065785af77af72c17c773517c15b248b067b4ad;hb=ae37d06c7d127817ba43850f0f898b793d42aea7#l4302" target="_blank" rel="noopener noreferrer">source</a>) for the actual freeing process.</p>
<p>However, <code>free</code>-ing a memory chunk "does not actually return it to the operating system for other applications to use. The <code>free()</code> call marks a chunk of memory as 'free to be reused' by the application, but from the operating system's point of view, the memory still 'belongs' to the application" (<a href="https://sourceware.org/glibc/wiki/MallocInternals#Free_Algorithm" target="_blank" rel="noopener noreferrer">source</a>) heap, meaning that the heap manager is still responsible of keeping track of the memory and reusing them when necessary.</p>
<p>That is why we use a circular linked list, with each chunk storing pointers to the previous and after, to organize the <code>free</code>-d chunks. Moreover, the size of the chunk is stored at the end of its memory area, <em>i.e.</em> the <code>chunk</code> pointer of the next chunk. Hence, the next chunk can use the size to access this <code>free</code>-d chunk and its header. When the next chunk is also <code>free</code>-d, we can use this property to <a href="https://cs.stackexchange.com/a/18234" target="_blank" rel="noopener noreferrer">coalesce</a> the two chunks.</p>
<p>Of course, the actual <code>free</code>-ing is much more complicated and the chunks will be put into different bins for efficient reallocation. You can read the official <a href="https://sourceware.org/glibc/wiki/MallocInternals" target="_blank" rel="noopener noreferrer">glibc wiki</a>, this more detailed <a href="https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/" target="_blank" rel="noopener noreferrer">blog post</a>, or the <a href="https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=e065785af77af72c17c773517c15b248b067b4ad;hb=ae37d06c7d127817ba43850f0f898b793d42aea7#l4302" target="_blank" rel="noopener noreferrer">source code for <code>_int_free</code></a> for more information.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-can-we-prevent-memory-leaks">How can we prevent memory leaks?<a href="https://shuye.dev/blog/malloc_chunk#how-can-we-prevent-memory-leaks" class="hash-link" aria-label="Direct link to How can we prevent memory leaks?" title="Direct link to How can we prevent memory leaks?">​</a></h2>
<p>It's probably time to come back to where we started: now that we've known what memory leaks are, and how they happened, how do we effectively prevent them?</p>
<ol>
<li>Always <code>delete</code> (<code>delete[]</code>) objects created with <code>new</code> (<code>new[]</code>).<!-- -->
<ul>
<li>The simplest thing to do, if you insist using <code>new</code>.</li>
</ul>
</li>
<li>Avoid calling <code>new</code> and <code>delete</code> explicitly<!-- -->
<ul>
<li><a href="https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#r11-avoid-calling-new-and-delete-explicitly" target="_blank" rel="noopener noreferrer">Explanation</a></li>
<li><strong>TL;DR</strong>: Use a resource handle instead of naked pointers, which can be leaked.</li>
<li>Solution: use a smart pointer like <code>unique_ptr</code> or <code>shared_ptr</code>.</li>
</ul>
</li>
<li>Never transfer ownership by a raw pointer (<code>T*</code>) or reference (<code>T&amp;</code>)<!-- -->
<ul>
<li><a href="https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#i11-never-transfer-ownership-by-a-raw-pointer-t-or-reference-t" target="_blank" rel="noopener noreferrer">Explanation</a></li>
<li><strong>TL;DR</strong>: it is unclear who should delete the pointer</li>
<li>Instead: return the object itself, or use a smart pointer</li>
</ul>
</li>
</ol>
<p>In general, requiring the programmer to manually free the resources is error-prone. You should consider <a href="https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rr-raii" target="_blank" rel="noopener noreferrer">managing resources automatically using resource handles and RAII</a> (Resource Acquisition is Initialization).</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="references--further-readings">References &amp; Further Readings<a href="https://shuye.dev/blog/malloc_chunk#references--further-readings" class="hash-link" aria-label="Direct link to References &amp; Further Readings" title="Direct link to References &amp; Further Readings">​</a></h2>
<ul>
<li>Stroustrup, Bjarne and Sutter, Herb. <a href="https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines" target="_blank" rel="noopener noreferrer">"C++ Core Guidelines"</a>. Updated Jun 17, 2021. Accessed Aug 08, 2021.</li>
<li>glibc wiki. <a href="https://sourceware.org/glibc/wiki/MallocInternals" target="_blank" rel="noopener noreferrer">"MallocInternals"</a>. Updated May 20, 2019. Accessed Aug 08, 2021.</li>
<li>Azeria Labs. <a href="https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/" target="_blank" rel="noopener noreferrer">"Heap Exploitation Part 2: Understanding the Glibc Heap Implementation"</a>. Accessed Aug 08, 2021.</li>
<li>CTF Wiki. <a href="https://ctf-wiki.org/pwn/linux/user-mode/heap/ptmalloc2/heap-structure/" target="_blank" rel="noopener noreferrer">"堆相关数据结构"</a> (in Chinese). Accessed Aug 10, 2021.</li>
<li>glibc Contributors. <a href="https://sourceware.org/git/?p=glibc.git;a=tree;h=6eb9f63e6c9197e967a8cc12a8b235335e5a873d;hb=ae37d06c7d127817ba43850f0f898b793d42aea7" target="_blank" rel="noopener noreferrer">glibc v2.34 source code</a>. Aug 2, 2021. Accessed Aug 8, 2021.</li>
<li>gcc Contributors. <a href="https://github.com/gcc-mirror/gcc/tree/releases/gcc-11.2.0" target="_blank" rel="noopener noreferrer">gcc v11.2.0 source code</a>. Jul 28, 2021. Accessed Aug 8, 2021.</li>
<li>StackOverflow. <a href="https://stackoverflow.com/questions/197675/how-does-delete-know-the-size-of-the-operand-array" target="_blank" rel="noopener noreferrer">"How does delete[] know the size of the operand array?"</a></li>
</ul>
<p>BTW, while Googling memory leaks, I found a wiki page <a href="https://wiki.bnl.gov/dayabay/index.php?title=Dealing_With_Memory_Leaks" target="_blank" rel="noopener noreferrer">"Dealing With Memory Leaks"</a> from Daya Bay Reactor Neutrino Experiment project hosted under Brookhaven National Lab's domain. I didn't know that Daya Bay Reactor also hosted a multinational research project 😂.</p>]]></content>
        <author>
            <name>Ye Shu</name>
            <uri>https://github.com/yechs</uri>
        </author>
        <category label="c++" term="c++"/>
        <category label="pwn" term="pwn"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Me and My Broken Site(s)]]></title>
        <id>https://shuye.dev/blog/welcome</id>
        <link href="https://shuye.dev/blog/welcome"/>
        <updated>2021-04-22T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[My personal website is finally up and running today! It is already 821 days after I purchased this domain (huh I'm such big a procrastinator). I also have a blog running on the subdomain blog.shuye.dev for some longer and possibly non tech-related blog posts.]]></summary>
        <content type="html"><![CDATA[<p>My personal website is finally up and running today! It is already 821 days after I purchased this domain (huh I'm such big a procrastinator). I also have a blog running on the subdomain <a href="https://blog.shuye.dev/" target="_blank" rel="noopener noreferrer">blog.shuye.dev</a> for some longer and possibly non tech-related blog posts.</p>
<p>This is not the first personal website I've ever made. I coded my very first personal website in 2014 using static HTML and CSS (that was the time when most websites were still using HTML 4.01 and you had to decide whether you want a "strict" version of HTML), after a bit of self-learning with W3Schools. In fact, I wasn't even learning from the true <a href="https://w3schools.com/" target="_blank" rel="noopener noreferrer">W3Schools</a>, but <a href="https://web.archive.org/web/20140103013237/http://w3school.com.cn/" target="_blank" rel="noopener noreferrer">an imitation of it</a>.</p>
<p>That was my first step, before I got into building more complicated (and dynamic!) websites using PHP, with the help from lecture videos of <a href="http://cs75.tv/2012/summer/" target="_blank" rel="noopener noreferrer">Harvard's open course CS75</a>. Shortly afterwards, I hosted my first dynamic website on the free hosting space RedHat OpenShift by 2016 (though it served more as a proxy server for me to get around the Internet censorship—that would be the topic of some other day). Sadly, all these codes were lost during the years (I didn't even know how to use git at that time).</p>
<p>Since then, I have hosted different sorts of personal websites: portfolios, WordPress blogs, and many lightweight alternatives like typecho or hugo. But to be honest I was more interested in the process of trying out new frameworks or toolsets, instead of actually settling down and writing something. And what use are websites of if not for sharing information?</p>
<p>In fact, that's what motivates me to still build blogs and websites to this day, in the year of 2021, when most people are turning to centralized social media platforms like WeChat, Instagram, Twitter ..., when small websites are almost extinct from public sight. I became so fed up by the frequent warnings of "sensitive words" that force me to water down and censor my comments so I finally decided to start (again) a website of my own to at least have a place to myself where I can actually write something undisturbed. And that's why, out of the innumerable possibilities, you are reading this article right now.</p>]]></content>
        <author>
            <name>Ye Shu</name>
            <uri>https://github.com/yechs</uri>
        </author>
        <category label="events" term="events"/>
        <category label="essays" term="essays"/>
    </entry>
</feed>