12. C/C++ Работа с динамической памятью

C/C++ Работа с динамической памятью

Работа с динамической памятью различна в языках C и C++, постараемся рассмотреть оба варианта

Язык C:

  • Стандартная библиотека cstdlib предоставляет четыре функции для управления памятью:

void * malloc ( size_t size);  // выделяет область памяти размера size. Данные не инициализируются.
void * calloc ( size_t nmemb , size_t size);  //выделяет массив из nmemb размера size. Данные инициализируются нулём.
void * realloc( void * ptr , size_t size); изменяет размер области памяти по указателю ptr на size (если возможно, то это делается на месте, путем добавления памяти, без переноса в другую область).
void free ( void * ptr); // освобождает область памяти, ранее выделенную одной из функций malloc/calloc/realloc.

Причечание:
• size_t — специальный целочисленный беззнаковый тип, может вместить в себя размер любого типа в байтах.
• Тип size_t используется для указания размеров типов данных, для индексации массивов и пр.
• void * — это указатель на нетипизированную память (раньше для этого использовалось char *).

 

Примеры:
• Для указания размера типа используется оператор sizeof().

// создание массива из 1000 int
int *m=(int *)malloc (1000 * sizeof ( int )); m[10] = 10;

// изменение размера массива до 2000
m=(int *)realloc(m, 2000 * sizeof (int ));

// освобождение массива
free(m);

// создание массива нулей
m=(int *)calloc(3000, sizeof (int ));

По окончанию работы с памятью важно освобождать память и занулять указатель!!!
Иначе возникнут утечки (leaks) в ходе которых в оперативной памяти будут участки неиспользуемой памяти, к которым нет доступа.
Желательно проверять, что указатель !=0 иначе при попытке очистить память будет ошибка.
free(m);
m = 0;

 

 

Язык C++:
Язык C++ предоставляет два набора операторов для выделения памяти:
1. new и delete — для одиночных значений,
2. new [] и delete [] — для массивов.
• Версия оператора delete должна соответствовать версии оператора new.

// выделение памяти под один int со значением 5
int *m= new int (5);
delete m; // освобождение памяти

// создание массива нулей m = new int [1000];
delete [] m; // освобождение памяти
m=null;
m=nullptr; //эта версия немного лучше (т.к. != 0)

По окончанию работы с памятью важно освобождать память и занулять указатель!!!
Иначе возникнут утечки (leaks) в ходе которых в оперативной памяти будут участки неиспользуемой памяти, к которым нет доступа.
Желательно проверять, что указатель !=0 иначе при попытке очистить память будет ошибка.

Проблемы при работе с памятью:

  • Проблемы производительности: создание переменной на стеке существенно менее ресурсоемка, чем выделение для неё динамической памяти.
  • Проблема фрагментации: выделение большого количества небольших сегментов способствует фрагментации памяти.
  • Утечки памяти:

Итог:
В динамической памяти стоит создавать «крупные переменные», работая с мелкими, простыми типами на стеке.
В ряде случаев м.б. удобнее сразу создать большой массив в динамической памяти под все «функции» программы, чем создавать множество мелких зон для «подпрограмм».
Всегда быть внимательным к утечкам памяти и следить за указателем (не переназначать его до удаления данных в динамической памяти)

КРАЙНЕ НЕ РЕКОМЕНДУЕТСЯ объединять подходы и методы работы с памятью языков С и C++, иначе код будет трудно читабельным и возможны ошибки.

Leave a Reply

Your email address will not be published. Required fields are marked *