Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 13.10.2017, 15:06   #1
Haric_110
Форумчанин
 
Регистрация: 03.03.2013
Сообщений: 102
Смущение Освобождение памяти из под динамического двумерного массива

Здравствуйте, товарищи-программисты и просто любители программировать на с++ (я, например, скорее к последним отношусь)!

Проблему ярко характеризует заголовок, тема и описывают комментарии в коде.
Должно быть, у меня какая-то очень тупая ошибка, даже заранее стыдно, но я не могу освободить память...
Код, представленный ниже, я хотел использовать в качестве тестирующей обёртки для решения определённой задачи.
Код:
#include <fstream>
/*здесь ещё один инклюдик с процедурой random_test_generator и другими процедурами...*/
#include <iostream>

int main() {
	std::ifstream input;
	unsigned int n, m, k, ind_1 = -1, ind_2 = 0, *i, test_num = 0;
	char **strings;
	while (true) {
		std::cout << "test_" << ++test_num << " generation...";
		random_test_generator();				// создаёт файл с тестовыми данными

		input.open("input.txt");
		input >> n >> m >> k;

		std::cout << '\n'
			<< "nst = " << n << ", ncl = " << m << ", k = " << k << '\n'
			<< "status... ";

		i = new unsigned int[n];

		strings = new char *[m];
		*strings = new char[m * n];

		while (ind_2 < n) i[ind_2] = ind_2++;

		ind_2 ^= ind_2;
		while (++ind_2 < m) strings[ind_2] = strings[ind_2 - 1] + n;

		ind_2 ^= ind_2;
		while (++ind_1 < m) {
			input >> strings[ind_1];
			while (ind_2 < n) strings[ind_1][ind_2++] -= 'a';
			ind_2 ^= ind_2;
		}
		input.close();					// после этого момента будут выполняться действия, но не работает обёртка.

		delete[] i;					// нормально удаляется
		delete[] *strings;				// выбрасывает исключение после выхода из оператора delete
		delete[] strings;

		std::cout << "done\n";
		ind_1 ^= ind_1--;
		ind_2 ^= ind_2;
	}
	return 0;
}
Пример генерируемого файла с небольшими параметрами на всякий случай прикладываю в приложения.
Вложения
Тип файла: txt input.txt (6.8 Кб, 125 просмотров)

Последний раз редактировалось Haric_110; 13.10.2017 в 15:55.
Haric_110 вне форума Ответить с цитированием
Старый 13.10.2017, 21:49   #2
Haric_110
Форумчанин
 
Регистрация: 03.03.2013
Сообщений: 102
По умолчанию

Эх, видать, ошибка не так очевидна...
Haric_110 вне форума Ответить с цитированием
Старый 14.10.2017, 01:37   #3
Croessmah
Вредный кошак
Участник клуба
 
Аватар для Croessmah
 
Регистрация: 14.10.2012
Сообщений: 1,159
По умолчанию

Для начала:
Код:
//while (ind_2 < n) i[ind_2] = ind_2++;
while (ind_2 < n) {
   i[ind_2] = ind_2;
   ++ind_2;
}
А дальше посмотрим.

Цитата:
Код:
ind_2 ^= ind_2;
Думаете, будет быстрее?

Последний раз редактировалось Croessmah; 14.10.2017 в 01:41.
Croessmah вне форума Ответить с цитированием
Старый 14.10.2017, 07:57   #4
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Двумерный массив - это массив указателей на указатели.


Код:
char **strings = new char *[n];
for (int i = 0; i < n; ++i)
strings[i] = new char[m];

Код:
for (int i = 0; i < n; ++i)
   delete [] strings[i];
delete [] strings;
В таком варианте работать с ним, как strings[i][j]

Но такое делают достаточно редко, чаще выделяют 1-мерный массив размера m * n, и работают типа *(string + i *n +j) через арифметику указателей. В таком варианте, память под данные будет в непрерывном блоке, можно его копировать через memcpy и т.д.

Последний раз редактировалось alexzk; 14.10.2017 в 08:03.
alexzk вне форума Ответить с цитированием
Старый 14.10.2017, 08:16   #5
Croessmah
Вредный кошак
Участник клуба
 
Аватар для Croessmah
 
Регистрация: 14.10.2012
Сообщений: 1,159
По умолчанию

Цитата:
Сообщение от alexzk Посмотреть сообщение
Двумерный массив - это массив указателей на указатели.
Смотря как сделаешь.
В варианте ТС делается всё за две аллокации,
а не за n + 1 аллокаций.
При этом сохраняется доступ по индексам.
Это весьма распространенный "прием",
если его вообще можно так назвать.
Croessmah вне форума Ответить с цитированием
Старый 14.10.2017, 08:40   #6
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Цитата:
Сообщение от Croessmah Посмотреть сообщение
Смотря как сделаешь.
В варианте ТС делается всё за две аллокации,
а не за n + 1 аллокаций.
При этом сохраняется доступ по индексам.
Это весьма распространенный "прием",
если его вообще можно так назвать.
Чета я не совсем логику улавливаю...

Здесь сделали массив указателей:
strings = new char *[m];

Здесь первому из указателей в массиве присвоили память m *n
*strings = new char[m * n];

А на кой черт остальные указатели в массиве m-1 чтука.
alexzk вне форума Ответить с цитированием
Старый 14.10.2017, 08:50   #7
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Цитата:
Сообщение от Haric_110 Посмотреть сообщение
Эх, видать, ошибка не так очевидна...
Вообще это все сплошная ошибка Взялись за С++ - делайте С++ и не морочте голову:

Код:
std::vector<std::vector<char>> strings;
strings.resize(m);
for (auto& v : strings) v.resize(n, 0);
Ну как-то так.
alexzk вне форума Ответить с цитированием
Старый 14.10.2017, 09:00   #8
Croessmah
Вредный кошак
Участник клуба
 
Аватар для Croessmah
 
Регистрация: 14.10.2012
Сообщений: 1,159
По умолчанию

Цитата:
Сообщение от alexzk Посмотреть сообщение
А на кой черт остальные указатели в массиве m-1 чтука.
Следом эти указатели "настраиваются" на свои "измерения".
Таким образом мы сохраняем возможность обращения по индексам.
Без имени.png
Croessmah вне форума Ответить с цитированием
Старый 14.10.2017, 09:08   #9
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Чепуха какая-то времен С.
Плохо, что ее в программу на С++ тащат. По-моему, или делай одномерный массив с арифметикой указателей, или делай класс, с перегрузкой операторов, если хочется "работы по индексам".
alexzk вне форума Ответить с цитированием
Старый 14.10.2017, 09:11   #10
Croessmah
Вредный кошак
Участник клуба
 
Аватар для Croessmah
 
Регистрация: 14.10.2012
Сообщений: 1,159
По умолчанию

Цитата:
Сообщение от alexzk Посмотреть сообщение
Чепуха какая-то
Если посмотреть код в первом сообщении, то там да. )))
Любитель сдвига вместо умножения на два.
Croessmah вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Утечка памяти [Освобождение памяти массива] denis76560 Общие вопросы Delphi 4 27.11.2016 18:20
Объявление динамического двумерного массива kineziz Общие вопросы C/C++ 4 27.05.2012 15:40
Освобождение памяти под динамический массив tsar_ Общие вопросы Delphi 7 24.12.2011 00:37
Матрица из двумерного динамического массива. Abrokadawr Фриланс 5 03.11.2011 22:28
Освобождение динамического массива? VintProg Общие вопросы Delphi 15 28.08.2009 10:41