Dynamic Memory Allocation

Notes

In this diagram of a program’s memory, the heap is a pool of available memory that can be allocated dynamically while your program is running.

Whereas a function's local (i.e. stack) variables disappear when the function returns, memory allocated from the heap will persist until it is explicitly given back to the operating system.

The C library provides a function called malloc() (short for memory allocation) that allocates a block of memory from the heap and returns a pointer to it.

Whenever your program needs fresh storage at run time that must outlast the current function, it can call malloc(), passing it the number of bytes needed. Since the sizes of data types vary from system to system, C provides the sizeof() operator for determining the size of a particular type. In this example, sizeof(int) * 10 evaluates to 40 bytes on the appliance, so we are asking the OS for a pointer to 40 bytes of memory.

**** Note that sizeof() is considered an operator not a function because it takes any kind of data type and returns the appropriate size, whereas a function must specify what type of argument it takes. ****

Normally malloc() returns a pointer to a block of newly allocated memory from the heap. However, if there is an error, or the heap has been exhausted, malloc() returns NULL.

For this reason, ALWAYS CHECK THE POINTER RETURNED BY MALLOC!! If the returned pointer is NULL, you must handle this case by signaling an error. Programs that don't perform this check can dereference NULL, which results in a segmentation fault.

When a program has finished using heap memory, it should release the storage by calling free() on the pointer that was originally produced by malloc().

All memory that is malloc'd must later be free'd (but only once), and only memory that was produced by malloc() should be free'd.

Let's walk through this program:

  • First, we ask the OS for a pointer to 4 bytes of memory in the heap.
  • Next, we check to make sure malloc() did not return NULL.
  • We then get an integer from the user, store it in the memory that malloc() gave us, and print the integer.
  • Finally, we free the malloc'd memory.

Slides ( / )

study50 slide
study50 slide
study50 slide
study50 slide
study50 slide

Out of Memory

Prerequisites:

Write a program that continuously mallocs a single byte until malloc(1) fails. Print out how many times malloc(1) was successful.

jharvard@run.cs50.net (~): ./a.out
33411839

Note that output may differ between runs, and your program might take a while to terminate :)

Try out some pseudocode here!
#include <stdio.h>
#include <stdlib.h>

int
main(void)
{
    // TODO
}

Free

Prerequisites:

Free all heap memory used in this program:

int main(void)
{
    char* ptr = malloc(sizeof(char) * 7);

    for (int i = 0; i < 6 i++)
        *(ptr + i) = ‘z’;

    ptr[6] = ‘\0’;

    while (*ptr != ‘\0’)
    {
        printf("%c", *ptr);
        ptr++;
    }

    // TODO: free heap memory!
}


Hint: Pay careful attention to pointer arithmetic!

Try out some pseudocode here!
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    char* ptr = malloc(sizeof(char) * 7);
     
    for (int i = 0; i < 6 i++)
    {
        *(ptr + i) = ‘z’;
    }
    
    ptr[6] = ‘\0’;

    while (*ptr != ‘\0’)
    {
        printf("%c", *ptr);
        ptr++;
    }

    // TODO: free heap memory
}

Videos

study50 video thumbnail

Wednesday, Week 4

An introduction to pointers