# Memory Management In C, you can manually manage memory to have greater control. - If you need to store information on a dynamic number of students, for example, it's wasteful and dangerous to assume a maximum size of e.g. 1000 students. (What if I give you only 50? How about 1001?) - Instead, you can dynamically allocate memory based on your input size, requesting it from the OS with functions such as `malloc`. # Stack and Heap Local variables are automatically allocated on the stack when they come into scope. They are deallocated (memory is freed) when they exit their scope. The stack grows from top to bottom. Manually allocated memory is put on the heap. The heap grows from bottom to top. # Functions `` ## malloc void* malloc(size_t size) - Request allocation of **size** bytes - Returns a void* to the allocated memoru - Returns NULL if allocation failed ## free free(void* p) - Frees block of memory starting at p - Must free in same scope of call to malloc ## memset void* memset(void s[n], int c, size_t n) - Sets first **n** bytes of memory pointed to by **s** with byte **c**. - Returns **s** (pointer to void) - Can clear memory area given by call to malloc (or use calloc) ## calloc void* calloc(size_t n, size_t size) - Request allocation of **n** elements of **size** bytes each - Clears allocated memory with 0 - Returns a void* to the allocated memoru ## realloc void* realloc(void* p, size_t size) - Resize memory to **size** bytes - Doesn't initialize new memory, see memset - If p is NULL -> same as malloc(size) # Example ```c char *p = malloc(sizeof(char * 64)); // char *p = malloc(sizeof(*p * 12)); <<-- *p is a char, same effect as above // always error check malloc if (p == NULL) { fprintf(stderr, "Call to malloc failed! Aborting...\n"); exit(1); } // use p strcpy(p, "malloced string"); puts(p); // free memory, else memory leak free(p); ```