Skip to main content

Dive Into Systems: Exercises

Section 2.4 Dynamic Memory Allocation

Checkpoint 2.4.1. Dynamic Memory Allocation.

    What is the difference between arr1 and arr2, defined as follows?
            int arr1[10];
    int *arr2;
    arr2  =  (int *) malloc(sizeof(int) * 10);
  • They are different sizes.
  • No. Both arr1 and arr2 can hold up to 10 int elements.
  • arr1 is allocated in stack memory, while arr2 is allocated in heap memory.
  • Correct!
  • arr1 stores ints, while arr2 stores pointers to ints.
  • Incorrect. Read the code again carefully!
  • arr1 is NULL, but arr2 contains values.
  • Incorrect. Neither array contains any values.

Checkpoint 2.4.2. Dynamic Memory Allocation (Q2).

    Why might one choose to allocate an array dynamically in heap memory using malloc rather than statically in stack memory? Select all that apply.
  • You want to avoid exceeding the size of stack memory.
  • Correct! The stack is of limited size.
  • The size of the array is not known until runtime.
  • Great work!
  • You want to provide more flexibility to grow or shrink the size of the array.
  • Correct! Unlike static arrays, you can change the size of a dynamically allocated array!
  • To automatically deallocate the array when the function returns.
  • Incorrect!

Checkpoint 2.4.3. Dynamic Memory Allocation (Q3).

    Given the function prototype:
    void *test_fun(int i);
    What is the meaning of void *?
  • test_fun returns a pointer to an unspecified type
  • Correct!
  • test_fun does not return a value
  • Incorrect.
  • test_fun returns NULL
  • Incorrect.

Checkpoint 2.4.4. Dynamic Memory Allocation (Active Code).

In the main function, 1.) write code to declare a static array named static_array with a fixed size of 5 integers. Similarly, 2.) write code to dynamically allocate an array named dynamic_array that will be used to store 5 integers. Finally, initialize the values in both arrays to be [1, 2, 3, 4, 5].
#include <stdio.h>

int main(void) {

    //write code to declare a static array named static_array
    //write code to dynamically allocate an array named dynamic_array
    //initialize the values in both arrays to be [1,2,3,4,5]

    return 0;
A sample implementation is shown below:
int static_array[5];
int *dynamic_array;
int i;

// allocate heap space for dynamic_array
dynamic_array = (int *) malloc(sizeof(int) * 5);

// Initialize arrays with values 1 to size
for (i = 0; i < 5; i++) {
     static_array[i] = i + 1;
     dynamic_array[i] = i + 1;

Checkpoint 2.4.5. Dynamic Memory Allocation (Q4).

    Given the following code, which of the calls to do_something are valid? Select all that apply.
    void do_something(int *array, int size);
    int arr1[10];
    int *arr2;
    arr2 = malloc(sizeof(int)*10);
    // assume some initialization code is here
    // call do_something here
  • do_something(arr1, 10);
  • Correct!
  • do_something(arr2, 10);
  • Correct!
  • do_something(&arr1, 10);
  • Incorrect.
  • do_something(&arr2, 10);
  • Incorrect.

Checkpoint 2.4.6. Dynamic Memory Allocation (Active Code).

Write a function that receives an array of int and its size as its two parameters and prints all the elements in the array.
#include <stdio.h>

       //write your code here!
A sample solution is shown below:
       //void print_array(int *array, int size) { //is also valid
void print_array(int array[], int size) {
    int i;

    for (i = 0; i < size; i++) {
        printf("%d ", array[i]);

Checkpoint 2.4.7. Fill In The Blank.

Given the code:
void init_array(double *array, int size);

int main(void) {
    int size;
    double *array2;

    size = 100;
    array2  = (double *) malloc(sizeof(double) * size);
    array2[0] = 2.0;
    init_array(array2, size);
    printf(“%f\n”, array2[0]);

void init_array(double *array, int size){
    array  = (double *) malloc(sizeof(double) * size);
    array[0] = 3.0;
What will main print out?

Checkpoint 2.4.8. Explore a larger program.

Consider the execution of the mallocstacktrace.c program:
#include <stdio.h>
#include <stdlib.h>

void foo(int *b, int c, int *arr, int n) ;
void blah(int *r, int s);

int main(void) {
    int x, y, *arr;

    arr = (int *)malloc(sizeof(int)*5);
    if (arr == NULL) {
	exit(1);   // should print out nice error msg first

    x = 10;
    y = 20;
    printf("x = %d y = %d\n", x, y);
    foo(&x, y, arr, 5);
    printf("x = %d y = %d arr[0] = %d arr[3] = %d\n",
	    x, y, arr[0],arr[3]);

    return 0;

void foo(int *b, int c, int *arr, int n) {
    int i;
    c = 2;
    for (i=0; i<n; i++) {
	arr[i] = i + c;
    *arr = 13;
    blah(b, c);

void blah(int *r, int s) {
    *r = 3;
    s = 4;


Step through the execution of this program. What is its output?
The program’s output is:
x = 10 y = 20
x = 3 y = 20 arr[0] = 13 arr[3] = 5


List the values of the array’s elements after the call to foo returns.
The array contents are:
13, 3, 4, 5, 6


Draw the contents of the stack and the heap at the point of execution immediately before the blah function returns.
Here is the execution stack drawn at the point shown in function blah: