APS105 L19 - Dynamic Memory
Parts of the memory that are used for a specific function are put in a stack, whereas the memory unrelated to the currently-running function is called the heap.
Requesting Memory in C
You can allocate specific areas in memory for whatever you wish using malloc(). C can't know what this memory is used for. Note that this requires the #include <stdlib.c> statement.
void* malloc(size_t size);
// size_t is a positive integer type
int *p = malloc(sizeof(int));
// this creates a pointer to an int
// however, the values in the memory cells are still undefined; it could be anything.
// you can initialize the value by dereferencing it
Example: Allocating space in memory using malloc()
#include <stdio.h>
#include <stdlib.h>
int *foo(void) {
int *p = malloc(sizeof(int));
// assigning the pointer p to an undeclared area in memory with size of 4 bytes
*p = 1; // dereferencing p, assigning the value of 1 to area in memory
return p;
}
int main(void) {
int *p = foo();
printf("*p: %d\n", *p);
return EXIT_SUCCESS;
}
malloc can run out of memory and return NULL
Thus, if you dereference the pointer that is pointing to the allocated memory, you are effectively trying to dereference NULL, which is invalid.
Memory Allocated with malloc() Must be Deallocated Manually
With variables declared within a function, the variables would be deallocated in memory once the function completed running.
malloc() doesn't do that though. Instead, we need to use free().
void free(void *ptr);
// deallocates the location in memory using pointer to location in memory
ptr = NULL;
// it is good practice to set the pointer to NULL after freeing it, so that your program isn't trying to get a random value from the pointer if it does try to use that memory.
free on.The value of at the address of the freed memory can be treated as "undefined behaviour".
Example: Deallocating Memory when we no Longer Use it
#include <stdio.h>
#include <stdlib.h>
int *foo(void) {
int *p = malloc(sizeof(int));
*p = 1;
return p;
}
int main(void) {
int *p = foo();
printf("*p: %d\n", *p);
free(p);
return EXIT_SUCCESS;
}
This is bad, since the longer the program runs, the more memory is wasted.
Using valgrind in Terminal to Check for Memory Leaks
If you use the terminal to run your C program, you can use valgrind to get a summary of what memory was allocated and for what purpose.
We can use valgrind build/valid-pointer to check.
Dynamically Allocating an Array
We can change the size of an array "on the fly" using malloc() and free().
Example: Setting size of an array based on input from user
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int arrayLength = 0;
do {
printf("Enter the length of the array: ");
scanf("%d", &arrayLength);
} while (arrayLength <= 0);
int *array = malloc(sizeof(int) * arrayLength);
// allocating the size of the array based on arrayLength
if (array == NULL) { return EXIT_FAILURE; }
// if there isn't enough space in memory, return NULL
// so that the program doesn't break down
randomizeArray(array, arrayLength);
printArray(array, arrayLength);
free(array);
array = NULL;
return EXIT_SUCCESS;
}