Правильное выделение и освобождение памяти для многомерных массивов в C и C++

Введение

Часто в процессе создания кода требуется работать с многомерными массивами. Простейшим примером двумерного массива является матрица. Массивы более высоких порядков (3-го и выше) называются тензорами.

Многие начинающие программисты допускают ошибки при освобождении памяти многомерных массивов.

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

Выделение памяти для матрицы

Назовём матрицу Matrix. Пусть её элементы будут представлены числами с плавающей точкой двойной точности (double). Объявление указателя такой матрицы выглядит следующим образом:

double **Matrix;

Пусть количество строк матрицы равняется numStrings, а столбцов — numColumns (целые беззнаковые числа). Сперва выделим память для строк:

Правильное выделение и освобождение памяти для многомерных массивов в C и C++, image #1

Теперь необходимо выделить память для элементов каждой строки:

Правильное выделение и освобождение памяти для многомерных массивов в C и C++, image #2

Здесь используется псевдоним типа size_t, обозначающий в C++ целое беззнаковое число. Альтернативой является использование unsigned int.

Память для элементов матрицы выделена, теперь её можно использовать по назначению.

Освобождение памяти матрицы

Освобождение памяти матриц следует выполнять в обратном порядке: сначала надо освободить элементы каждой строки и только после этого освободить память массива строк:

Правильное выделение и освобождение памяти для многомерных массивов в C и C++, image #3

После освобождения памяти не допускаются какие-либо обращения к элементам матрицы. Указатель матрицы можно использовать повторно после нового выделения памяти (по аналогии с предыдущим примером).

Выделение памяти для тензоров

Объявим Tensor размерностью N x M x K. Такой тензор можно представить как массив матриц. Выделение памяти происходит следующим образом. Сперва выделяется память для массива двумерных массивов, затем для одномерных массивов, а затем для конкретных элементов:

Правильное выделение и освобождение памяти для многомерных массивов в C и C++, image #4

Этот код можно слегка оптимизировать:

Правильное выделение и освобождение памяти для многомерных массивов в C и C++, image #5

Преимущество этой оптимизации в том, что исключается лишний проход вдоль тензора по пространству N.

Освобождение памяти тензоров

Здесь всё происходит аналогично: необходимо освободить память в обратном порядке относительно её выделения:

Правильное выделение и освобождение памяти для многомерных массивов в C и C++, image #6

Здесь также можно применить оптимизацию:

Правильное выделение и освобождение памяти для многомерных массивов в C и C++, image #7

Заключение

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

217 views·2 shares