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

94 lines
8.5 KiB
Markdown
Raw Normal View History

2018-10-12 16:00:59 -04:00
---
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` . Если вы не будете следовать этому шаблону, обычно будет передан отказ от сегментации, и программа выйдет из строя. Эти ошибки могут быть временными и сложными для отладки - например, освобожденная память обычно не сразу восстанавливается системой, а оборванные указатели могут сохраняться некоторое время и, похоже, работают.