Memory allocation

The allocation of memory (i.e. obtaining some memory from the operating system) can be automatic or manual. Automatic allocation is done transparently by the program; in this case, deallocation (giving the memory back to the operating system) is automatic too, and occurs at the end of the scope. Automatic allocation always occurs on the stack. Manual allocation is done explicitly by the user, and deallocation must be done manually too. Manual allocation always occurs on the heap. Variables are always allocated automatically on the stack. The memory pointed to by pointers, however, is manually assigned to each pointer and may be manually allocated on the heap.

Examples.

  1. The following code declares that myChar is a variable of type char, reserves 1 byte on the stack, and fills that byte with the 8-bit number 120 (the ASCII code for `x'). The allocated stack byte is deallocated (released) at the closing brace.
    {
      ...
      char myChar = 'x';
      ...
    }
    
  2. The following code declares that ptrChar is a pointer of type char*, reserves 4 bytes on the stack, and fills those bytes with the 32-bit address of the memory where the value corresponding to the myChar variable is kept. The allocated stack space is released at the closing brace.
    {
      ...
      char* ptrChar = &myChar;
      ...
    }
    
  3. The first line of the following code declares that ptrDouble is a pointer of type double* and reserves 4 bytes on the stack (enough for a 32-bit memory address). The second line obtains 8 bytes of heap memory (enough to contain a double) and assigns its 32-bit address to the pointer ptrDouble. The third line writes the floating point number 0.2 into the heap memory area whose address is stored in ptrDouble. Notice that in order to actually use manually allocated heap memory, one needs to allocate some stack space to hold the address. The deallocation of the stack space occurs at the closing brace, but the deallocation of the heap space does not occur. In fact, this is an example of memory leak: we allocate some heap space, assign the address to a pointer, but the pointer is deallocated (and the address lost) before the heap space is deallocated; at this point, there is no way to deallocate the heap space, apart from the operating system automatically reclaiming the memory at the end of the execution.
    {                             // 1
      double* ptrDouble;          // 2
      ptrDouble = new double;     // 3
      *ptrDouble = 0.2;           // 4
    }                             // 5
    
  4. This is like the example above, but revised so that memory leak does not occur. In line 2, a pointer ptrOther of type double is declared, and 4 bytes are allocated on the stack for holding a 32-bit address. Lines 4-6 are as above. In line 7 we copy the 32-bit address held in ptrDouble to ptrOther (this means that the heap memory address where the number 0.2 is stored is held in two different pointers). At line 8, as above, the stack space for ptrDouble is released and the address within it is lost. However, since ptrOther was allocated outside the scope being closed at line 8, ptrOther still exists after line 8: since ptrOther contains the address for the heap memory allocated in line 5, we can issue a manual delete command to release the heap memory, at line 9. Although the heap memory is released, the stack memory used for storing the ptrOther pointer is not: this is released at line 10 (the end of the scope).
    {                             // 1
      double* ptrOther;           // 2
      {                           // 3
        double* ptrDouble;        // 4
        ptrDouble = new double;   // 5
        *ptrDouble = 0.2;         // 6
        ptrOther = ptrDouble;     // 7
      }                           // 8
      delete ptrOther;            // 9
    }                             // 10
    

Leo Liberti 2008-01-12