Create an account


Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Stack vs Heap. What’s the Difference and Why Should I Care?

#1
Stack vs Heap. What’s the Difference and Why Should I Care?

<div style="margin: 5px 5% 10px 5%;"><img src="http://www.sickgaming.net/blog/wp-content/uploads/2018/06/stack-vs-heap-whats-the-difference-and-why-should-i-care.jpg" width="1436" height="747" title="" alt="" /></div><div><div><img src="http://www.sickgaming.net/blog/wp-content/uploads/2018/06/stack-vs-heap-whats-the-difference-and-why-should-i-care.jpg" class="ff-og-image-inserted" /></div>
<p class="graf graf--p graf-after--figure">I’m four months into the curriculum at <a class="markup--anchor markup--p-anchor" href="https://www.holbertonschool.com/">Holberton School</a> and we’ve solved multiple problems using the malloc, realloc, calloc and free functions in the C programming language. What better way to build a solid foundation of how memory gets allocated then to write a technical post on the stack versus the heap?</p>
<h4 class="graf graf--h4 graf-after--p">This article explains in depth:</h4>
<blockquote class="graf graf--blockquote graf-after--h4">
<p>What are the five segments of memory?</p>
</blockquote>
<blockquote class="graf graf--blockquote graf-after--blockquote">
<p>What is the stack?</p>
</blockquote>
<blockquote class="graf graf--blockquote graf-after--blockquote">
<p>What is the heap?</p>
</blockquote>
<blockquote class="graf graf--blockquote graf-after--blockquote">
<p>How does understanding the two make you a better software engineer?</p>
</blockquote>
<h4 class="graf graf--h4 graf-after--blockquote">What are the five segments of memory?</h4>
<p class="graf graf--p graf-after--h4">When we write applications, files, or any logic that is typed in an editor and executed on the computer, the computer has to allocate memory for the program to run. The memory that is assigned to a program or application in a computer can be divided into five parts. The amount of memory that get’s assigned to an application depends on the computer’s architecture and will vary across most devices, but the variable that remains constant is the five parts of an application’s memory which are the heap, stack, initialized data segment, uninitialized data segment, and the text segment.</p>
<p class="graf graf--p graf-after--figure">The <em class="markup--em markup--p-em">initialized data segment</em>consists of all the global and static variables that are initialized when a file gets compiled. The <em class="markup--em markup--p-em">uninitialized data segment</em> consists of all global and static variables that are initialized to zero or do not have explicit initialization in source code.</p>
<p class="graf graf--p graf-after--p">At Holberton, most of the time we are not concerned about the uninitialized data segment because when we compile our programs with <code class="markup--code markup--p-code">gcc</code>, we use the flags, <code class="markup--code markup--p-code">-Wall -Wextra -pedantic -Werror</code> and we use an internal stylistic checker called <code class="markup--code markup--p-code">betty</code> which treats warning as errors when uninitialized variables are present. Having unused variables in our programs gets flagged and is not a best practice. The <em class="markup--em markup--p-em">text segment</em>, also known as the code segment, contains the machine instructions which make up your program. The text segment is often read-only and prevents a program from accidentally modifying its instructions.</p>
<h4 class="graf graf--h4 graf-after--p">What is the stack?</h4>
<p class="graf graf--p graf-after--h4">The stack is a segment of memory where data like your local variables and function calls get added and/or removed in a last-in-first-out (LIFO) manner. When you compile a program, the compiler enters through the main function and a stack frame is created on the stack. A <a class="markup--anchor markup--p-anchor" href="http://www.cs.uwm.edu/classes/cs315/Bacon/Lecture/HTML/ch10s07.html">frame</a>, also known as an <em class="markup--em markup--p-em">activation record</em> is the collection of all data on the stack associated with one subprogram call. The main function and all the local variables are stored in an initial frame.</p>
<p>Program vs Stack usage</p>
<p class="graf graf--p graf-after--figure">In the picture above, we have one stack frame on the stack that holds the main function, along with the local <code class="markup--code markup--p-code">a, b and sum</code> variables. After using the <code class="markup--code markup--p-code">printf()</code> function the frame we created along with the local variables are only accessible in memory for the duration of the frame are no longer accessible after returning the 0 value from the function.</p>
<p class="graf graf--p graf-after--p">What happens with the stack when we call multiple functions? To illustrate the stack in it’s <a class="markup--anchor markup--p-anchor" href="http://www.i-programmer.info/babbages-bag/263-stacks.html">LIFO</a> manner, let’s solve a problem using recursion. When we call multiple functions in our application, we use multiple stack frames in a last-in-first-out approach meaning that the last stack frame we’ve created on the stack is the first stack that will be released after the function is done executing its logic. Let’s go over an example of printing out the name “Holberton” recursively and show how our code affects the stack memory segment.</p>
<p>Yes, I have a whiteboard on the back of my door at my house.</p>
<p class="graf graf--p graf-after--figure">When we compile our code using <code class="markup--code markup--p-code">gcc _putchar.c 0-puts_recursion.c 0-main.c</code> , the compiler enters our program through <code class="markup--code markup--p-code">int main(void)</code> and creates a frame with the function <code class="markup--code markup--p-code">int main(void)</code> and <code class="markup--code markup--p-code">_puts_recursion("Holberton")</code> living on that frame as illustrated on the image above. When the compiler runs into the <code class="markup--code markup--p-code">_puts_recursion()</code> function, it calls that function and creates another stack frame on top of the previous stack frame where <code class="markup--code markup--p-code">int main(void)</code> lives. We are now in our second stack frame in our program and have entered in the <code class="markup--code markup--p-code">_puts_recursion(char *s)</code>function where <code class="markup--code markup--p-code">*s</code> is equal to <code class="markup--code markup--p-code">'H'</code> and is only accessible in that stack frame. Because <code class="markup--code markup--p-code">'H'</code> does not equal <code class="markup--code markup--p-code">'\0'</code> , we will continue with our function calls and execute the <code class="markup--code markup--p-code">_putchar('H')</code> function and enter into the same function <code class="markup--code markup--p-code">_puts_recursion(++s)</code>. The argument <code class="markup--code markup--p-code">++s</code> moves the memory address of the <code class="markup--code markup--p-code">*s</code> one byte because the size of a char is 1 byte on our machine, and now <code class="markup--code markup--p-code">_puts_recursion</code> is calling the function as <code class="markup--code markup--p-code">_puts_recrusion('o')</code> . Each time the <code class="markup--code markup--p-code">_puts_recursion</code> function is called, a new stack frame is put on the stack until we hit the terminating condition which is <code class="markup--code markup--p-code">if (*s == '\0')</code>.</p>
<p class="graf graf--p graf-after--p">Every time a new stack frame is created, the stack pointer moves with it until it reaches the terminating condition. A stack pointer is a small register that stores the address of the last program request in a frame. When we hit the terminating condition, we execute our logic, then start to unwind the stack or pop off stack frames in the last-in-first-out manner until we reach out <code class="markup--code markup--p-code">return(0)</code> logic in the <code class="markup--code markup--p-code">int main(void)</code> function in our first stack frame.</p>
<p class="graf graf--p graf-after--p">If you don’t have a terminating case for the recursive example above, the stack will continue to grow in size adding additional stack frames on-top of each other, moving the stack pointer upward on each call, against the heap, which will be explained in the next section. In a recursive function , if there is no valid terminating condition, the stack will grow until you’ve completed consumed all the memory that’s been allocated for your program by the operating system. When the stack pointer exceeds the stack bound, you have a condition called <em class="markup--em markup--p-em">stack overflow</em>. Bad things happen when you have a stack overflow.</p>
<p class="graf graf--p graf-after--p">Let’s first refer back to the other four segments of your application’s memory which were the uninitialized and initialized data segments, text segment and stack segment. These four segments have a constant memory size during compilation. The memory size for these four segments is predetermined by your operating system before compiling your programs. When software engineers write programs that consume large amounts of memory from a machine, they have to consider where and how much memory is being consumed in their application.</p>
<p class="graf graf--p graf-after--p">The max stack size is constant and predetermined before a program is compiled. At Holberton, we use a Linux Ubuntu/Trusty64 distributions. To find information about the stack size and other neat limits, type the command below into your terminal.</p>
<p class="graf graf--p graf-after--p"><code class="markup--code markup--p-code">ulimit -a</code></p>
<p class="graf graf--p graf-after--p">Where <code class="markup--code markup--p-code">ulimit</code> is a function that gets and sets user limits and the <code class="markup--code markup--p-code">-a</code> flag lists all the current limits.</p>
<p>Stack size is 8.192MB of memory.</p>
<p class="graf graf--p graf-after--figure">If the stack is limited in size and a program needs more memory for it to execute, where can a software engineer pull memory from for his/her application? This is where the heap comes into play.</p>
<h4 class="graf graf--h4 graf-after--p">What is the heap?</h4>
<p class="graf graf--p graf-after--h4">The heap is the segment of memory that is not set to a constant size before compilation and can be controlled dynamically by the programmer. Think of the heap as a “free pool” of memory you can use when running your application. The size of the heap for an application is determined by the physical constraints of your RAM (Random access memory) and is generally much larger in size than the stack.</p>
<p class="graf graf--p graf-after--p">We use memory from the heap when we don’t know how much space a data structure will take up in our program, when we need to allocate more memory than what’s available on the stack, or when we need to create variables that last the duration of our application. We can do that in the C programming language by using <a class="markup--anchor markup--p-anchor" href="https://linux.die.net/man/3/malloc">malloc</a>, <a class="markup--anchor markup--p-anchor" href="https://linux.die.net/man/3/realloc">realloc</a>, <a class="markup--anchor markup--p-anchor" href="https://linux.die.net/man/3/calloc">calloc</a> and/or <a class="markup--anchor markup--p-anchor" href="https://linux.die.net/man/1/free">free</a>. Check out the example below.</p>
<p>Allocating 4000 bytes of memory to our program, then releasing it.</p>
<p class="graf graf--p graf-after--figure">We allocate memory from the heap using the <code class="markup--code markup--p-code">malloc()</code> function. The argument we want to include in malloc is the amount of memory we want to allocate to our application, in bytes. <code class="markup--code markup--p-code">Malloc</code> returns a void pointer that is type casted into an integer pointer that now points to the first address in memory for our 4000 byte long memory. We can now store information in those memory addresses and do as we please to that information for the duration of our program or for the duration of our function because we have a pointer that references the first memory address from the newly allocated heap memory.</p>
<p class="graf graf--p graf-after--p">If you aren’t intentionally creating variables that last the duration of your application from the heap, you always want to release the memory back to the machine using the <code class="markup--code markup--p-code">free()</code> function. If you don’t release the memory using the free() function, you have memory that will persist throughout your program. If we do not release the memory from our program before terminating the application, our application has memory leaks. If your application has enough memory leaks, it can consume more memory than is physically available and can cause programs to crash. This is why we use a program called <code class="markup--code markup--p-code">valgrind</code>. <a class="markup--anchor markup--p-anchor" href="http://valgrind.org/">Valgrind</a> is easy to use and checks for memory leaks.</p>
<p>Valgrind being used. 4,000 bytes allocated. 0 bytes leaks</p>
<p class="graf graf--p graf-after--figure">Another thing to consider while using the heap, the pointer variables created on the heap are accessible by any function, anywhere in your program, as long as the memory is still persistent and hasn’t been free.</p>
<h4 class="graf graf--h4 graf-after--p">How does understanding the stack and heap make you a better software engineer?</h4>
<p class="graf graf--p graf-after--h4">If you understand the advantages and disadvantages of using the stack vs the heap for your application, then it gives you a strategic advantage for creating scalable programs. You, the programmer, have to decide when to use memory from the stack vs heap based on each problem you are trying to solve.</p>
<p class="graf graf--p graf-after--p">If you have a variable like an array or struct that needs to be stored in a large block memory, needs to persist throughout the lifetime of your application and could change in size throughout the duration of your program, then you should allocate it from the heap.</p>
<p class="graf graf--p graf-after--p">If you need to create helper functions with variables that only persist within the lifetime of the function, then you should allocate memory from the stack. Memory from the stack is easier to keep track of because the memory is only locally available in the function call which does not persist after the function is completed and is managed by the CPU.</p>
<p>Photo credit: <a class="markup--anchor markup--figure-anchor" href="https://www.gribblelab.org/CBootCamp/7_Memory_Stack_vs_Heap.html#orgheadline1">Gribble Lab</a></p>
<p class="graf graf--p graf-after--figure">Questions, comments or concerns, feel free to comment below, follow me or find me on Twitter @ NTTL_LTTN.</p>
<h4 class="graf graf--h4 graf-after--p">References:</h4>
<p class="graf graf--p graf-after--h4">My Code School. (February 23rd, 2013). Pointers and dynamic memory — stack vs heap. . Retrieved from <a class="markup--anchor markup--p-anchor" href="https://www.youtube.com/watch?v=_8-ht2AKyH4">https://www.youtube.com/watch?v=_8-ht2AKyH4</a></p>
<p class="graf graf--p graf-after--p">Paul Gribble (2012). C Programming Boot Camp — 7. Memory: Stack vs Heap. [Blog post]. Retrieved from <a class="markup--anchor markup--p-anchor" href="https://www.gribblelab.org/CBootCamp/7_Memory_Stack_vs_Heap.html#orgheadline1">https://www.gribblelab.org/CBootCamp/7_Memory_Stack_vs_Heap.html#orgheadline1</a></p>
<p class="graf graf--p graf-after--p">GeeksforGeeks. Memory Layout of C Programs. [Blog post]. Retrieved from <a class="markup--anchor markup--p-anchor" href="https://www.geeksforgeeks.org/memory-layout-of-c-program/">https://www.geeksforgeeks.org/memory-layout-of-c-program/</a></p>
<p class="graf graf--p graf-after--p">Sandra Henry-Stocker. (November 18th, 2012). NETWORK WORLD — Setting limits with ulimit. [Blog post]. Retrieved from <a class="markup--anchor markup--p-anchor" href="https://www.networkworld.com/article/2693414/operating-systems/setting-limits-with-ulimit.html">https://www.networkworld.com/article/2693414/operating-systems/setting-limits-with-ulimit.html</a></p>
<p class="graf graf--p graf-after--p">Valgrind Developers (2000–2017). Valgrind. Retrieved from <a class="markup--anchor markup--p-anchor" href="http://valgrind.org/">http://valgrind.org/</a></p>
<p class="graf graf--p graf-after--p graf--trailing">Die.net Linux Documentation. Retrieved from <a class="markup--anchor markup--p-anchor" href="https://linux.die.net/">https://linux.die.net/</a></p>
<div class="contextual-links-region panel-pane pane-entity-field pane-node-body">
<div class="field field-name-body field-type-text-with-summary field-label-hidden">
<div class="field-items">
<div class="field-item even">
<div class="section-content">
<div class="section-inner sectionLayout--insetColumn">
<p class="graf graf--li graf-after--li graf--trailing"><em>This article was produced in partnership with Holberton School and originally appeared on <a href="https://medium.com/@nickteixeira/stack-vs-heap-whats-the-difference-and-why-should-i-care-5abc78da1a88">Medium</a>.</em></p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Reply



Forum Jump:


Users browsing this thread:
3 Guest(s)

Forum software by © MyBB Theme © iAndrew 2016