freeCodeCamp/guide/russian/c/dynamic-memory-management/index.md

94 lines
8.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

---
title: Dinamic Memory Management
localeTitle: Управление динамической памятью
---
# Управление динамической памятью
Иногда вам нужно выделять пространства памяти в куче, также называемой динамической памятью. Это особенно полезно, если во время компиляции вы не знаете, насколько велика структура данных (например, массив).
## Пример
Вот простой пример, в котором мы выделяем массив, запрашивающий у пользователя выбор измерения
```C
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int arrayDimension,i;
int* arrayPointer;
scanf("Please insert the array dimension:%d",arrayDimension);
arrayPointer = (int*)malloc(sizeof(int)*arrayDimension);
if(arrayPointer == NULL){
printf("Error allocating memory!");
return -1;
}
for(i=0;i<arrayDimension;i++){
printf("Insert the %d value of the array:",i+1);
scanf("%d\n",arrayPointer[i]);
}
free(arrayPointer);
return 0;
}
```
Как вы можете видеть, чтобы выделить пространство в динамической памяти, вам нужно знать, как работают указатели на C. Магическая функция здесь - это `malloc` который будет возвращать как вывод указателя void (это указатель на область неизвестного типа данных) в новое пространство памяти, которое мы только что выделили. Давайте посмотрим, как использовать эту функцию шаг за шагом:
## Выделение массива во время выполнения
```C
sizeof(int)
```
Начнем с `sizeof` . `malloc` должен знать, сколько места выделяется для ваших данных. Фактически переменная `int` будет использовать меньше места для хранения, а затем `double` . Обычно небезопасно принимать размер любого типа данных. Например, хотя большинство реализаций C и C ++ в 32-битных системах определяют тип int как четыре октета, этот размер может измениться, когда код портируется в другую систему, нарушая код. `sizeof` мере того, как его имя предполагает, генерирует размер переменной или типа данных.
```C
arrayPointer = (int*) malloc(sizeof(int) * arrayDimension);
```
В этом примере malloc выделяет память и возвращает указатель на блок памяти. Размер выделенного блока равен количеству байтов для одного объекта типа int, умноженного на `arrayDimension` , при условии, что система имеет достаточно свободного места. Но что, если у вас недостаточно места или `malloc` не может выделить его по другим причинам?
## Проверка вывода malloc
Обычно этого не происходит, но очень полезно проверять значение переменной указателя после выделения нового пространства памяти.
```C
if(arrayPointer == NULL)
printf("Error allocating memory!");
```
Это также будет очень полезно во время фазы отладки и предотвратит некоторые возможные ошибки, используя последнюю функцию, используемую в примере.
## Слово на бесплатном ()
Обычно переменные автоматически де-распределяются, когда их область действия уничтожается, освобождая память, которую они используют. Это простое не происходит, когда вы вручную выделяете память с помощью `malloc` . Чтобы предотвратить утечку памяти в более сложных программах и чтобы не создавать мусор в системе, вам необходимо освободить область памяти, которая была недавно использована до прекращения выполнения кода.
```C
free(arrayPointer);
```
В конце вы точно поймете, что проверка значения `arrayPointer` необходимо для предотвращения ошибки с использованием `free` функции. Если значение `arrayPointer` равно `NULL` вы могли бы исправить какую-то ошибку.
## Другие функции, подобные malloc
Иногда вам нужно не только резервировать новую область памяти для ваших операций, но также может потребоваться инициализировать все байты до нуля. Для этого используется `calloc` . В других случаях вы хотите изменить размер памяти, на которую указывает указатель. Например, если у вас есть указатель, действующий как массив размера `n` и вы хотите изменить его на массив размера `m` , вы можете использовать `realloc` .
```C
int *arr = malloc(2 * sizeof(int));
arr[0] = 1;
arr[1] = 2;
arr = realloc(arr, 3 * sizeof(int));
arr[2] = 3;
```
## Общие ошибки
Неправильное использование распределения динамической памяти часто может быть источником ошибок, как вы видели раньше. Наиболее распространенные ошибки:
* Не проверять наличие сбоев Выделение памяти не гарантирует успеха, и вместо этого может возвращать нулевой указатель. Используя возвращаемое значение, не проверяя, выполнено ли выделение, вызывает неопределенное поведение. Это обычно приводит к сбою (из-за возникшей ошибки сегментации при разыменовании нулевого указателя), но нет никакой гарантии, что произойдет сбой, поэтому полагаться на это также может привести к проблемам.
* Утечка памяти Неспособность освободить память с помощью `free` ведет к созданию памяти без повторного использования, которая больше не используется программой.
* Логические ошибки Все распределения должны следовать той же схеме: выделение с помощью `malloc` , использование для хранения данных, используя Deallocation `free` . Если вы не будете следовать этому шаблону, обычно будет передан отказ от сегментации, и программа выйдет из строя. Эти ошибки могут быть временными и сложными для отладки - например, освобожденная память обычно не сразу восстанавливается системой, а оборванные указатели могут сохраняться некоторое время и, похоже, работают.