Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p><strong>Note:</strong> This answer is <em>way</em> too long. I'll pare it down sometime. Meanwhile, comment if you can think of useful edits.</p> <hr> <p>To answer your questions, we first need to define two areas of memory called the <strong>stack</strong> and the <strong>heap</strong>.</p> <h1>The stack</h1> <p>Imagine the stack as a stack of boxes. Each box represents the execution of a function. At the beginning, when <code>main</code> is called, there is one box sitting on the floor. Any local variables you define are in that box.</p> <h2>A simple example</h2> <pre><code>int main(int argc, char * argv[]) { int a = 3; int b = 4; return a + b; } </code></pre> <p>In this case, you have one box on the floor with the variables <code>argc</code> (an integer), <code>argv</code> (a pointer to a char array), <code>a</code> (an integer), and <code>b</code> (an integer).</p> <h2>More than one box</h2> <pre><code>int main(int argc, char * argv[]) { int a = 3; int b = 4; return do_stuff(a, b); } int do_stuff(int a, int b) { int c = a + b; c++; return c; } </code></pre> <p>Now, you have a box on the floor (for <code>main</code>) with <code>argc</code>, <code>argv</code>, <code>a</code>, and <code>b</code>. On top of that box, you have another box (for <code>do_stuff</code>) with <code>a</code>, <code>b</code>, and <code>c</code>.</p> <p>This example illustrates two interesting effects.</p> <ol> <li><p>As you probably know, <code>a</code> and <code>b</code> were passed-by-value. That's why there is a <em>copy</em> of those variables in the box for <code>do_stuff</code>.</p></li> <li><p>Notice that you don't have to <code>free</code> or <code>delete</code> or anything for these variables. When your function returns, the box for that function is destroyed.</p></li> </ol> <h2>Box overflow</h2> <pre><code> int main(int argc, char * argv[]) { int a = 3; int b = 4; return do_stuff(a, b); } int do_stuff(int a, int b) { return do_stuff(a, b); } </code></pre> <p>Here, you have a box on the floor (for <code>main</code>, as before). Then, you have a box (for <code>do_stuff</code>) with <code>a</code> and <code>b</code>. Then, you have another box (for <code>do_stuff</code> calling itself), again with <code>a</code> and <code>b</code>. And then another. And soon, you have a stack <em>overflow</em>.</p> <h2>Summary of the stack</h2> <p>Think of the stack as a stack of boxes. Each box represents a function executing, and that box contains the local variables defined in that function. When the function returns, that box is destroyed.</p> <h2>More technical stuff</h2> <ul> <li>Each "box" is officially called a <em>stack frame</em>.</li> <li>Ever notice how your variables have "random" default values? When an old stack frame is "destroyed", it just stops being relevant. It doesn't get zeroed out or anything like that. The next time a stack frame uses that section of memory, you see bits of old stack frame in your local variables.</li> </ul> <h1>The heap</h1> <p>This is where dynamic memory allocation comes into play.</p> <p>Imagine the heap as an endless green meadow of memory. When you call <code>malloc</code> or <code>new</code>, a block of memory is allocated in the heap. You are given a pointer to access this block of memory.</p> <pre><code>int main(int argc, char * argv[]) { int * a = new int; return *a; } </code></pre> <p>Here, a new integer's worth of memory is allocated on the heap. You get a pointer named <code>a</code> that points to that memory.</p> <ul> <li><code>a</code> is a local variable, and so it is in <code>main</code>'s "box"</li> </ul> <h1>Rationale for dynamic memory allocation</h1> <p>Sure, using dynamically allocated memory seems to waste a few bytes here and there for pointers. However, there are things that you just can't (easily) do without dynamic memory allocation.</p> <h2>Returning an array</h2> <pre><code>int main(int argc, char * argv[]) { int * intarray = create_array(); return intarray[0]; } int * create_array() { int intarray[5]; intarray[0] = 0; return intarray; } </code></pre> <p>What happens here? You "return an array" in <code>create_array</code>. In actuality, you return a pointer, which just points to the part of the <code>create_array</code> "box" that contains the array. What happens when <code>create_array</code> returns? Its box is destroyed, and you can expect your array to become corrupt at any moment.</p> <p>Instead, use dynamically allocated memory.</p> <pre><code>int main(int argc, char * argv[]) { int * intarray = create_array(); int return_value = intarray[0]; delete[] intarray; return return_value; } int * create_array() { int * intarray = new int[5]; intarray[0] = 0; return intarray; } </code></pre> <p>Because function returning does not modify the heap, your precious <code>intarray</code> escapes unscathed. Remember to <code>delete[]</code> it after you're done though.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload