Если вы выделили данные с помощью malloc / calloc, вам нужно освободить данные.
Дополнение из-за любопытного комментария @Julia Childe:
Хорошо, смысл выделения динамической памяти состоит в том, что она будет оставаться там до тех пор, пока вы ее явно не освободите. Это позволяет вам передавать указатели как от функций, так и к функциям, и вы не ограничены областью действия конкретной функции, то есть main.
Таким образом, вы можете выделить память для данных, когда вам нужно, а не заранее, таким образом, динамический память.
Если бы у нас не было этой способности, нам пришлось бы знать, сколько памяти мы использовали бы во время компиляции.
Надеюсь, это уберет некоторые знаки вопроса.