Skip to content

Using Malloc

In this tour we will explore the use of malloc to create an array of double’s in memory. We are focusing on the basics of using malloc and free here, and how these can be used to allocate space in memory. The program we create will be very simple, just creating an array of a variable size, populate it with double values, and then print these values out. In the advanced tour we will look at making this into a more usable utility, so focus on the mechanics here.

Create your project

We can get started as we have with other projects:

  1. Work out where you are going to save this project, create the folder if needed, and open it in VS Code.
  2. Create a new dynamic-test.cpp code file.
  3. Copy in your utilities.h and utilities.cpp files from the shared utilities activity. This will contain the read_integer and read_double functions we need. If either of these are missing, you should code them in your utilities files.
  4. Add the following code to your dynamic-test.cpp file to kick things off:
/* dynamic-test.cpp - from the field guide. written by ... */
#include <cstdlib>
#include "splashkit.h"
#include "utilities.h"
int main()
{
//todo: create a pointer to refer to your data
// and a size to keep track of how many items we can store
//todo: read the size of the array from the user
// and allocate the memory for the data
//todo: populate the data
//todo: print the data
//tood: free the memory
return 0;
}

Creating a pointer and size variable

To make use of the heap we need a pointer. Start off by adding two variables at the top of main. We need a pointer to a double, and an integer called size. The pointer will refer to the data on the heap, while the size variable will retain the information on the number of elements we allocated in memory. You will also need to cast the returned data from an untyped pointer (void *) to a pointer to double data (double *).

Also add in the code to check that this succeeded, and exit the program if you could not allocate the number of bytes requested.

Code this up yourself - but you can check our solution if you get stuck.

  • You should end up with something like this:

    /* dynamic-test.cpp - from the field guide. written by ... */
    #include <cstdlib>
    #include "splashkit.h"
    #include "utilities.h"
    int main()
    {
    // Retain a pointer to the data we allocate on the heap
    double *data_ptr;
    // Remember the number of elements we allocate (nothing else will)
    int size;
    //todo: read the size of the array from the user
    // and allocate the memory for the data
    //todo: populate the data
    //todo: print the data
    //tood: free the memory
    return 0;
    }

Allocating space on the heap

Now for the magic. Use the read_integer function to ask the user how many values they want to store. There is no set maximum here, so they can enter any number of elements. When you use malloc, you will need to pass in the size in bytes you want. The sizeof function can be used to get the size of the double type, which you multiply by the number of elements the user wants to get the number of bytes to be allocated.

Have a go at this yourself, but if you need, you can check our solution below.

  • /* dynamic-test.cpp - from the field guide. written by ... */
    #include <cstdlib>
    #include "splashkit.h"
    #include "utilities.h"
    int main()
    {
    // Retain a pointer to the data we allocate on the heap
    double *data_ptr;
    // Remember the number of elements we allocate (nothing else will)
    int size;
    // Get the size of the array to create - and allocate space on heap
    size = read_integer("Enter the number of items to store: ");
    data_ptr = (double *)malloc(size * sizeof(double));
    // Check we could allocate the memory
    if (data_ptr == NULL)
    {
    write_line("Memory allocation failed");
    return 1;
    }
    //todo: populate the data
    //todo: print the data
    //tood: free the memory
    return 0;
    }

Populate and print the data

This step should not be any different to working with an array stored in a local variable or parameter. Use a for loop to iterate over the newly allocated memory - this is now on the heap, but the code to manipulate it does not really change. This is very basic processing, but it should help you see that there is really no difference in the steps or code you use when working with the heap. So the main thing with this is just knowing when to allocate the space, and when to free it.

You really should be able to do this without hints, but the solution is here if needed.

  • If you really need this you should probably go back and work through the earlier chapters, either in control flow or in working with multiples. Remember with all of this, the main thing is to really understand each step as you progress. If it isn’t making sense, then talk with others who are studying this or connect with others who really understand programming. Talking through your understanding should help reinforce things.

    /* dynamic-test.cpp - from the field guide. written by ... */
    #include <cstdlib>
    #include "utilities.h"
    #include "splashkit.h"
    int main()
    {
    // Retain a pointer to the data we allocate on the heap
    double *data_ptr;
    // Remember the number of elements we allocate (nothing else will)
    int size;
    // Get the size of the array to create - and allocate space on heap
    size = read_integer("Enter the number of items to store: ");
    data_ptr = (double *)malloc(size * sizeof(double));
    // Check we could allocate the memory
    if (data_ptr == NULL)
    {
    write_line("Memory allocation failed");
    return 1;
    }
    //Populate the data - assigning values to each element of the array
    for (int i = 0; i < size; i++)
    {
    data_ptr[i] = read_double("Enter a number: ");
    }
    //Access the values
    for (int i = 0; i < size; i++)
    {
    write_line("Value at index " + to_string(i) + ": " + to_string(data_ptr[i]));
    }
    //tood: free the memory
    return 0;
    }

Cleaning up

Lastly we should clean up the memory we allocated. Freeing this memory is not really needed in this case as the memory will be freed when the program terminates. However, in larger programs we will want to be able to allocate and free memory as we finish with it. Use the free function to free the memory allocation, and remember to set the pointer to refer to NULL so that it is not accidentally used again.

  • /* dynamic-test.cpp - from the field guide. written by ... */
    #include <cstdlib>
    #include "utilities.h"
    #include "splashkit.h"
    int main()
    {
    // Retain a pointer to the data we allocate on the heap
    double *data_ptr;
    // Remember the number of elements we allocate (nothing else will)
    int size;
    // Get the size of the array to create - and allocate space on heap
    size = read_integer("Enter the number of items to store: ");
    data_ptr = (double *)malloc(size * sizeof(double));
    // Check we could allocate the memory
    if (data_ptr == NULL)
    {
    write_line("Memory allocation failed");
    return 1;
    }
    //Populate the data - assigning values to each element of the array
    for (int i = 0; i < size; i++)
    {
    data_ptr[i] = read_double("Enter a number: ");
    }
    //Access the values
    for (int i = 0; i < size; i++)
    {
    write_line("Value at index " + to_string(i) + ": " + to_string(data_ptr[i]));
    }
    //free the memory
    free(data_ptr);
    data_ptr = NULL;
    return 0;
    }

Reflect

We now have a program that can allocate any number of elements in the data array, and we have seen that the code you use to access this is the same as it was when we were manipulating data on the stack.