Освобождение памяти от динамического массива

Периодически возникает необходимость в освобождении памяти от переменных, созданных во время работы программы. Это особо актуально, когда программа создает большие динамические массивы, которые используются в жизненном цикле программы ограниченное количество раз и в дальнейшем только занимают лишнее пространство в оперативной памяти.

В языке программирования C++ оператор delete возвращает память, выделенную оператором new, обратно в кучу. А теперь давайте представим задачу, в которой нам необходимо объявить динамический массив для решения локальных проблем, а потом можно будет забыть об этом массиве. Проблема не столь велика, если нам изначально известен размер массива и он крайне мал. Поверьте, во многих приложениях так и сделано: разработчик просто забыл о существовании массива, а программа - нет.

Но в случае, когда размер динамического массива зависит от данных введенных пользователем, проблема разростается и может забить всю память. Рассмотрим пример генератора паролей, где пользователь задает количество символов (длину пароля), а нача задача - сгенерировать, вывести и ждать...

void genpass(unsigned int len) {
	char * str = new str[len];
	char chars[] = {'0','1','2','3','4',
		    '5','6','7','8','9',
		    'A','B','C','D','E','F',
		    'G','H','I','J','K',
		    'L','M','N','O','P',
		    'Q','R','S','T','U',
		    'V','W','X','Y','Z',
		    'a','b','c','d','e','f',
		    'g','h','i','j','k',
		    'l','m','n','o','p',
		    'q','r','s','t','u',
		    'v','w','x','y','z'
		    };

	for (unsigned int ix = 0; ix < len; ++ix){
		str[ix] = chars[rand() % sizeof(chars)];
	}
	return str;
}

Казалось бы, в программе достаточно вызвать данную функцию и забыть. Но представьте себе, что вы хотите сгенерировать пароль длиной N*10^6 символов. После того как пароль сгенерирован, выведен на экран, массив символов висит в памяти до тех пор, пока вы сидите и посимвольно переписываете пароль и пока программа не завершит свою работу. Долго... Но достаточно использовать delete и проблема решена. Но заметьте, память освобождается там, где ее заняли. Вот пример неверной работы:

int main(int argc, char **argv) {
	//setlocale(LC_ALL, "rus");
	unsigned int X, lines_count = 1, ix = 0;
	cout << "Введите длину строки, которую необходимо сгенерировать: ";
	cin >> X;

	char * str = genstr(X);
	cout << "Сгенерированная строка:" << endl << str << endl;

	delete [] str;

	system("PAUSE");
	return 0;
}

В этом примере память не освободится, так как сам массив создан и инициирован в функции genpass и только genpass знает какой участок памяти необходимо освободить. Но достаточно лишь немного преобразить код и всё будет работать прекрасно.

void genpass(char * str, unsigned int len) {
	char chars[] = {'0','1','2','3','4',
		    '5','6','7','8','9',
		    'A','B','C','D','E','F',
		    'G','H','I','J','K',
		    'L','M','N','O','P',
		    'Q','R','S','T','U',
		    'V','W','X','Y','Z',
		    'a','b','c','d','e','f',
		    'g','h','i','j','k',
		    'l','m','n','o','p',
		    'q','r','s','t','u',
		    'v','w','x','y','z'
		    };

	for (unsigned int ix = 0; ix < len; ++ix){
		str[ix] = chars[rand() % sizeof(chars)];
	}
}

int main(int argc, char **argv) {
	//setlocale(LC_ALL, "rus");
	unsigned int X, lines_count = 1, ix = 0;
	cout << "Введите длину строки, которую необходимо сгенерировать: ";
	cin >> X;

	char * str = new char[X]
        genstr(str, X);
	cout << "Сгенерированная строка:" << endl << str << endl;

	delete [] str;

	system("PAUSE");
	return 0;
}