<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Suvijak Vinyunavan</title>
    <description>The latest articles on DEV Community by Suvijak Vinyunavan (@suvijak_vinyunavan_1f9ff9).</description>
    <link>https://dev.to/suvijak_vinyunavan_1f9ff9</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3147737%2Fe5287bab-1184-45a1-856d-7bfc812eec60.jpg</url>
      <title>DEV Community: Suvijak Vinyunavan</title>
      <link>https://dev.to/suvijak_vinyunavan_1f9ff9</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/suvijak_vinyunavan_1f9ff9"/>
    <language>en</language>
    <item>
      <title>The Heap Memory</title>
      <dc:creator>Suvijak Vinyunavan</dc:creator>
      <pubDate>Mon, 30 Jun 2025 21:35:56 +0000</pubDate>
      <link>https://dev.to/suvijak_vinyunavan_1f9ff9/the-heap-memory-5ali</link>
      <guid>https://dev.to/suvijak_vinyunavan_1f9ff9/the-heap-memory-5ali</guid>
      <description>&lt;h2&gt;
  
  
  The Heap
&lt;/h2&gt;

&lt;p&gt;In the previous &lt;a href="https://dev.to/suvijak_vinyunavan_1f9ff9/the-stack-why-its-fast-and-how-it-works-elp"&gt;article&lt;/a&gt;, we discussed stack memory. In this article, we’ll complete the answer to the question: “Why is the stack faster than the heap?”, and also touch on why the heap is typically larger, but slower than the stack.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Use the Heap 🔨
&lt;/h2&gt;

&lt;p&gt;A natural way to introduce heap memory is by showing a working example of how it’s used in programs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Access 🗄️&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Heap memory is a region that a program accesses by explicitly requesting a block of memory from the operating system. Unlike stack memory, data stored on the heap remains valid after a function exits.&lt;/p&gt;

&lt;p&gt;For instance, when a function contains stack-allocated variables, those variables are automatically deallocated when the function returns. Attempting to access them afterward leads to undefined behavior, since the memory may have been overwritten.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;stacktest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// Pointer to stack memory&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Allocated memory at: %p&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Returning pointer to stack memory (not recommended)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;calloctest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;calloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Allocated memory at: %p&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;sptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stacktest&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;hptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;calloctest&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Allocated stack memory at: %p&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;sptr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Allocated heap memory at: %p&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;hptr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Stack memory value: %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;sptr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Access stack memory&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Heap memory value: %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;hptr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Access heap memory&lt;/span&gt;

    &lt;span class="n"&gt;free&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;hptr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Free heap memory&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Allocated memory at: 00000006C899F590
Allocated memory at: 0000011A01D49540
Allocated stack memory at: 00000006C899F590
Allocated heap memory at: 0000011A01D49540
Stack memory value: -929434080
Heap memory value: 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;stacktest&lt;/code&gt; creates a zero-initialized array on the stack and returns a pointer to the array on the stack. &lt;code&gt;calloctest&lt;/code&gt; allocates a zero-initialized memory span on the heap and returns a pointer to the memory location.&lt;/p&gt;

&lt;p&gt;In this case, the stack array we attempted to access contains corrupted values, not the zero we initialized it with. This is an example of stack corruption, where the memory was reused or overwritten after the function exited. This is due to the stack being a contiguous memory block which the program and functions use to perform operations they need. This is not how the stack is supposed to be used. Stack memory should not be accessed when it has left the scope, even though accessing it is still possible.&lt;/p&gt;

&lt;p&gt;In contrast, the heap-allocated memory remains intact and returns the expected zero. This is because &lt;a href="https://en.cppreference.com/w/c/memory/calloc" rel="noopener noreferrer"&gt;calloc&lt;/a&gt; initializes the allocated memory to zero, and the memory is allocated in an arbitrary location in the memory, making it much less susceptible to being randomly corrupted by other function calls or random memory access.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Size ↔️&lt;/strong&gt;&lt;br&gt;
The heap is also allowed to be much larger than the stack. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;StackOverflow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Allocate 800MB on the stack&lt;/span&gt;
    &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;100000000&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(process 56272) exited with code -1073741571 (0xc00000fd). // Stack overflow
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Allocating &lt;code&gt;800MB&lt;/code&gt; on the stack causes a stack overflow because it exceeds the default stack size (on Windows it's about &lt;code&gt;1MB&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;In contrast, the heap handles large allocations without crashing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;HeapNoOverflow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Allocate 800MB on the heap&lt;/span&gt;
    &lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;calloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Memory allocation failed!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Allocated memory at: %p"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Free memory&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Allocated memory at: 0x1e2c1fd0070
(process 53076) exited with code 0 (0x0).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Heap memory is not subject to a strict size cap like the stack, and thus 800MB can be asked from the heap without much problem. It can also be allocated from arbitrary locations in virtual memory.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Does the Heap Work?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To understand heap allocation, it helps to know a few key terms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🍿Kernel: The core part of an operating system, responsible for managing CPU time, memory, and hardware interaction at the lowest level.&lt;/li&gt;
&lt;li&gt;📄Page: A fixed-size memory block (typically 4096 bytes) used by the kernel to manage memory. Memory is allocated in pages rather than individual bytes for efficiency.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Allocation&lt;/strong&gt;&lt;br&gt;
Heap memory is allocated differently from the stack. The stack typically has a fixed size (e.g., 1MB on Windows), pre-allocated when a program starts. In contrast, the heap must be requested at runtime from the OS.&lt;/p&gt;

&lt;p&gt;When you call malloc, the C standard library first tries to find space in memory pages already assigned to the process. If no space is available, it performs a system call to the kernel to request additional memory pages.&lt;/p&gt;

&lt;p&gt;The kernel may:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;    Return a pointer to the allocated memory,&lt;/li&gt;
&lt;li&gt;    Or return MAP_FAILED to indicate allocation failure.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This address is passed back through the system layers from the kernel to the C library to malloc, and finally to the caller.&lt;/p&gt;

&lt;p&gt;This is much more complicated than the stack, where allocation is often just a pointer subtractions and pointer arithmetics.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftmjr8l6i4btp7zcqabst.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftmjr8l6i4btp7zcqabst.png" alt="Flow chart of the process. Arrows pointing from a box labeled " width="752" height="312"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Why Is the Heap Slower?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The complexity of heap allocation — requiring coordination between:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The C runtime,&lt;/li&gt;
&lt;li&gt;The operating system kernel,&lt;/li&gt;
&lt;li&gt;Bookkeeping data structures for memory blocks and pages,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…makes it significantly slower than stack allocation.&lt;/p&gt;

&lt;p&gt;Additionally, heap memory must be manually managed with malloc and free, introducing more opportunities for bugs like memory leaks, double frees, and dangling pointers.&lt;/p&gt;

&lt;p&gt;This means heap allocation is powerful but comes with cost:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Slower due to system calls and metadata tracking,&lt;/li&gt;
&lt;li&gt;Harder to manage due to manual deallocation,&lt;/li&gt;
&lt;li&gt;Larger and more flexible than stack memory.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use heap memory only when necessary, such as when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The data must outlive a function,&lt;/li&gt;
&lt;li&gt;The size is too large for the stack,&lt;/li&gt;
&lt;li&gt;Or the lifetime is dynamic and unpredictable.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>c</category>
      <category>cpp</category>
      <category>beginners</category>
      <category>learning</category>
    </item>
    <item>
      <title>The Stack: Why It’s Fast and How It Works</title>
      <dc:creator>Suvijak Vinyunavan</dc:creator>
      <pubDate>Sat, 24 May 2025 17:18:55 +0000</pubDate>
      <link>https://dev.to/suvijak_vinyunavan_1f9ff9/the-stack-why-its-fast-and-how-it-works-elp</link>
      <guid>https://dev.to/suvijak_vinyunavan_1f9ff9/the-stack-why-its-fast-and-how-it-works-elp</guid>
      <description>&lt;p&gt;While many programmers are familiar with the concept of the stack, a common question arises: Why is it faster than the heap, even though both reside in the same physical memory? This article aims to answer those questions to the very low level to satisfy the thirst for understanding of some curious individuals out there.&lt;/p&gt;

&lt;p&gt;Let’s not waste any more time and dive into the depth of the stack memory architecture.&lt;/p&gt;

&lt;h3&gt;
  
  
  📚What is the stack?
&lt;/h3&gt;

&lt;p&gt;The stack memory, allocated for every local variable and function calls, follows a strict, well-known, &lt;strong&gt;Last in first out (LIFO)&lt;/strong&gt;data structure: the latest item has to be removed first in order to access the previous stack. Each segment of the stack, which corresponds to each allocations and scope, is called a “stack frame”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjytc1rxdmf0aqaa76vyp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjytc1rxdmf0aqaa76vyp.png" alt="Image portraying how stack data structure works" width="501" height="231"&gt;&lt;/a&gt;&lt;br&gt;
(Figure 1: stack data structure illustration)&lt;/p&gt;
&lt;h3&gt;
  
  
  🧪An Example in C and Assembly.
&lt;/h3&gt;

&lt;p&gt;To better understand the stack memory, we need an example to follow by and explain.&lt;/p&gt;

&lt;p&gt;Supposed you call a function - &lt;em&gt;add()&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int add(int j, int k) {
    int a = 10;
    int b = j + k;
    return b;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which compiles to the following assembly(I promise it’s not as scary, I will explain them through) looks like:&lt;br&gt;
add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        push    {r11, lr}
        mov     r11, sp
        sub     sp, sp, #16
        str     r0, [r11, #-4]
        str     r1, [sp, #8]
        mov     r0, #10
        str     r0, [sp, #4]
        ldr     r0, [r11, #-4]
        ldr     r1, [sp, #8]
        add     r0, r0, r1
        str     r0, [sp]
        ldr     r0, [sp]
        mov     sp, r11
        pop     {r11, lr}
        bx      lr
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To understand the stack and how it’s allocated, we need to introduce some terminology and conventions first:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;📚 The stack frame is a region of memory allocated on the call stack for each function call in a program, which in the lower level, is the area between the frame pointer &lt;code&gt;fp&lt;/code&gt; and the top stack pointer &lt;code&gt;sp&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;☝️Frame pointer, together with the stack pointer, are the anchor points which the entire stack will operate relative to. They will never be changed throughout the entire process, and only change when the stack frame change ie. new stack allocation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;⏬The stack grows conventionally downwards, which means that when we allocate a stack on top of the existing one, the memory address of the new stack is lower than the previous one.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;📝&lt;code&gt;r11&lt;/code&gt; refers to a register in this case used as the frame pointer, and &lt;code&gt;sp&lt;/code&gt; refers to the stack pointer&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  🧱Breaking down the assembly
&lt;/h3&gt;

&lt;p&gt;Every time a stack has to be allocated the computer does the following&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        push    {r11, lr}
        mov     r11, sp
        sub     sp, sp, #16
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;push    {r11, lr}&lt;/code&gt; instructs the processor to put anything inside &lt;code&gt;r11&lt;/code&gt; which is currently the previous stack’s frame pointer, and &lt;code&gt;lr&lt;/code&gt; (link register used for returning from a function) onto the stack and decrements sp by 4 per each item, 8 in total.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;mov     r11, sp&lt;/code&gt; sets the frame pointer to the stack pointer&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally &lt;code&gt;sub     sp, sp, #16&lt;/code&gt; decrements &lt;code&gt;sp&lt;/code&gt; by 16 to make space for the 16 bytes we need for the function’s local variables and parameters.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6js1jsoltalyat39cfmm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6js1jsoltalyat39cfmm.png" alt="Image visualizing how the stack allocation works" width="800" height="740"&gt;&lt;/a&gt;&lt;br&gt;
(Figure 2: stack allocation step by step illustration)&lt;/p&gt;

&lt;p&gt;This concludes the stack allocation. The memory region between the stack pointer (&lt;code&gt;sp&lt;/code&gt;) and the frame pointer (&lt;code&gt;r11&lt;/code&gt;) constitutes the current function’s stack frame.&lt;/p&gt;
&lt;h3&gt;
  
  
  🔠Variables
&lt;/h3&gt;

&lt;p&gt;On line 7, we can see the assembly associated with initializing the variable &lt;code&gt;a&lt;/code&gt; to 10:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        str     r0, [sp, #4]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This instruction stores the value from register &lt;code&gt;r0&lt;/code&gt;, which currently holds the value 10 from the previous &lt;code&gt;mov&lt;/code&gt; instruction, into the memory location at an offset of 4 bytes from the stack pointer.&lt;/p&gt;

&lt;p&gt;This convoluted way of refering to a place in memory is required for the flexibility of the function to be called whenever and wherever in the code, since all the local variables would be just offsets in the frame itself. Different compilers have different approaches to how to use the stack, but essentially they all use location relative to the stack position for local variables.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feiwhwuzqdurcv84nddab.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feiwhwuzqdurcv84nddab.png" alt="Image portraying how local variable works" width="381" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You might wonder where do these memories come from? The truth is, all processes on the system get &lt;strong&gt;preallocated a stack&lt;/strong&gt; space it can use without requesting for more memory, by default about 1 - 8MB depends on the operating system. This means that programs already have the stack memory they need already allocated to them, but this also means that the stack is limited to only the space allocated for them at the beginning of the program. This limited preallocation is the reason why using too much of the stack memory (ie. from deep recursive function or an array too big) often leads to a stack overflow error.&lt;/p&gt;

&lt;p&gt;The mechanics used to allocate the memory being essentially moving pointers up and down &lt;strong&gt;requiring only a few instructions&lt;/strong&gt; is a major factor contributing to the exceptionally quick allocation of the stack memory, compared to heap memory which requires complicated book keepings of the entire heap area and operating system calls for more memory, making the stack memory far better suited for local small allocation such as variables, which does not need to persist through to other scope of the program.&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅To Summarize
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Stack allocation is fast due to simple pointer arithmetic.&lt;/li&gt;
&lt;li&gt;The CPU provides specific instructions optimized for stack operations.&lt;/li&gt;
&lt;li&gt;Stack memory is preallocated, eliminating the need for dynamic memory requests during execution.&lt;/li&gt;
&lt;li&gt;Stack size is determined at program start, and memory is automatically reclaimed when a function exits.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>assembly</category>
      <category>memory</category>
      <category>learning</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
