10/15/2018 - 12:09 AM

Dynamic Memory Allocation

Dynamic Memory Allocation

Static Memory Allocation:

If we declare a variable, and declare another pointer variable:
  int a;
  int* b;

This is static way of allocating memory. When we are compiling the program, memory will be allocated.

But what if we don't know how much memory we need at the compile time. An obvious time when we don't know how much memory to allocate, is when user is required to input some data. So the user will only input the data when the program is running, not compiling. That's why we have no idea how much memory we need to allocate for user's input. Especially if user is inputing a string. it could be very long. There is no way we would know how long the input string will be. That's why see other snippet when dealing with input strings we often use dynamic memory allocation.

Dynamic memory allocation is using pointers to allocate memory at running time, not at compiling time.

Here is an example of user inputing a string, and we can see we dynamically allocate memory space according to how long the user inputed the string. The length of the memory block is decided by the length of the inputed string: strlen(s) + 1.

    // get a string
    char *s = get_string("s: ");
    if (!s)
        return 1;
    // allocate memory for another string
    char *t = malloc((strlen(s) + 1) * sizeof(char));
    if (!t)
        return 1;
    // copy string into memory
    for (int i = 0, n = strlen(s); i <= n; i++)
        t[i] = s[i];
Dynamically allocated memory comes from a pool of memory known as the heap. Statically allocated memory will be in the memory area called stack.

Mostly if you give a variable a name, it will probably live in the stack. If you don't give variable a name, it will be at heap.

C uses malloc() to dynamically allocate memory. When requested, malloc() will go to heap and look for memory blocks to allocate. After obtaining memory block for you, it doesn't give that memory block a name, it will just return a pointer to that memory.

If it can't find suitable memory block, it will return NULL. So everytime we use malloc(), we always need to check if the returned pointer is NULL or not. If it's NULL we wouldn't want to continue dereferencing it.

// statically obtain an integer
	int x;

// dynamically obtain an integer
	int *px = malloc(sizeof(int));

// array of floats on the stack
	float stack_array[x];

// array of floats on the heap
	float *heap_array = malloc( x * sizeof(float));
	malloc() is allocating a chunck of memory that are next to each other, same like an array. The address of each memory block are continuous.

For example:

int *x = malloc(10 * sizeof(int));

It's same as declaring an array of 10 integers: int x[10];

After we allocate memory using malloc(), we can access it using array:

int *x = malloc(10 * sizeof(int));
x[9] = 50;
printf("you inputted %i.\n, x[9]);

	Free Dynamic Allocated Memories:

If you statically allocate memory, it will be automatically free after the function has finished using it. But dynamically allocated memory is not automatically returned when the function is done using it.

If we don't manually free the dynamically allocated memories, the memories will just stay there and accumulate, that will cause system's performance to go down. That is called memory leak.

That's why when you finish working with dynamically allocated memory, you must free() it.

For example:

  char *word = malloc(50 * sizeof(char));

// do stuff with word

// now we are done working with that block

Three golden rules:

1. Every block of memory that you malloc() must subsequently be free() d.

2. Only memory you malloc() should be free() d. If statically allocated memories, we don't need to free() them.

3. Do not free() a block of memory more than once.