Динамическая память в языке C

Динамическая память в языке C

Динамическая память — это память, которая выделяется во время выполнения программы. В языке C для этого используются функции из стандартной библиотеки stdlib.h, такие как malloc(), calloc(), realloc() и free(). Использование динамической памяти позволяет гибко управлять объемом памяти, который требуется программе.

В отличие от статической памяти, когда программа заранее определяет все необходимые массивы и переменные, динамическая память позволяет выделять память по мере необходимости и освобождать ее, когда она больше не нужна.

Функции для работы с динамической памятью

malloc()

Функция malloc() выделяет блок памяти заданного размера в байтах и возвращает указатель на начало этого блока. Если память не может быть выделена, возвращается NULL.


            #include <stdio.h>
            #include <stdlib.h>
            
            int main() {
                int *arr;
                int size = 5;
            
                // Выделение памяти для массива из 5 элементов типа int
                arr = (int*)malloc(size * sizeof(int));
                if (arr == NULL) {
                    printf("Ошибка выделения памяти.\n");
                    return 1;
                }
            
                // Заполнение массива значениями
                for (int i = 0; i < size; i++) {
                    arr[i] = i * 10;
                }
            
                // Вывод массива
                for (int i = 0; i < size; i++) {
                    printf("%d ", arr[i]);
                }
                printf("\n");
            
                free(arr);  // Освобождение памяти
                return 0;
            }
                        

Этот пример выделяет память для массива из 5 целых чисел с помощью malloc(), заполняет его значениями и затем освобождает память с помощью free().

calloc()

Функция calloc() работает аналогично malloc(), но дополнительно инициализирует все элементы выделенной памяти значением 0.


            #include <stdio.h>
            #include <stdlib.h>
            
            int main() {
                int *arr;
                int size = 5;
            
                // Выделение памяти и инициализация нулями
                arr = (int*)calloc(size, sizeof(int));
                if (arr == NULL) {
                    printf("Ошибка выделения памяти.\n");
                    return 1;
                }
            
                // Вывод массива
                for (int i = 0; i < size; i++) {
                    printf("%d ", arr[i]);
                }
                printf("\n");
            
                free(arr);  // Освобождение памяти
                return 0;
            }
                        

В этом примере calloc() выделяет память для массива из 5 целых чисел и инициализирует их значением 0.

Изменение размера памяти с realloc()

Функция realloc() позволяет изменить размер уже выделенного блока памяти. Если новый размер больше, то в случае необходимости будет выделена дополнительная память. Если новый размер меньше, лишняя память освобождается.


            #include <stdio.h>
            #include <stdlib.h>
            
            int main() {
                int *arr;
                int size = 5;
            
                // Выделение памяти для массива
                arr = (int*)malloc(size * sizeof(int));
                if (arr == NULL) {
                    printf("Ошибка выделения памяти.\n");
                    return 1;
                }
            
                // Заполнение массива значениями
                for (int i = 0; i < size; i++) {
                    arr[i] = i * 10;
                }
            
                // Изменение размера массива
                size = 7;
                arr = (int*)realloc(arr, size * sizeof(int));
                if (arr == NULL) {
                    printf("Ошибка изменения размера памяти.\n");
                    return 1;
                }
            
                // Заполнение новых элементов массива
                for (int i = 5; i < size; i++) {
                    arr[i] = i * 10;
                }
            
                // Вывод массива
                for (int i = 0; i < size; i++) {
                    printf("%d ", arr[i]);
                }
                printf("\n");
            
                free(arr);  // Освобождение памяти
                return 0;
            }
                        

В этом примере сначала выделяется память для массива из 5 элементов, затем размер массива увеличивается до 7 с помощью realloc(), и новые элементы заполняются значениями.

Освобождение памяти с free()

После того как динамическая память больше не требуется, она должна быть освобождена с помощью функции free(). Это предотвращает утечку памяти — ситуацию, когда память остаётся занятой, хотя она больше не используется.


            #include <stdio.h>
            #include <stdlib.h>
            
            int main() {
                int *arr;
                int size = 5;
            
                // Выделение памяти для массива
                arr = (int*)malloc(size * sizeof(int));
                if (arr == NULL) {
                    printf("Ошибка выделения памяти.\n");
                    return 1;
                }
            
                // Заполнение массива значениями
                for (int i = 0; i < size; i++) {
                    arr[i] = i * 10;
                }
            
                // Освобождение памяти
                free(arr);
                printf("Память освобождена.\n");
            
                return 0;
            }
                        

Этот пример показывает, как после использования динамической памяти мы должны вызвать free() для освобождения памяти, занятой массивом.

Общие рекомендации

Работа с динамической памятью требует аккуратности, поскольку неправильное выделение или освобождение памяти может привести к ошибкам, таким как утечка памяти или доступ к неинициализированной памяти.

  • Всегда проверяйте, что функции malloc(), calloc(), и realloc() вернули ненулевой указатель, что значит успешное выделение памяти.
  • После завершения работы с динамической памятью не забывайте использовать free() для ее освобождения.
  • Если вы хотите увеличить или уменьшить размер блока памяти, используйте realloc().