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

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

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

Восстановить пароль

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

Ответ
 
Опции темы Поиск в этой теме
Старый 06.11.2012, 12:28   #1
perceptron2013
Новичок
Джуниор
 
Регистрация: 06.11.2012
Сообщений: 1
По умолчанию Освобождение памяти в бинарном дереве?

Не получается освободить память командой delete рекурсивным вызовом функции fDel
Код:
#include <conio.h>
#include <iostream>
using namespace std;
int Count=0;
//Структура элемента дерева
struct binTree{
	binTree *p1;
	binTree *p2;
	int n;
};
//функция создания бинарного дерева
binTree *makeTree(int N){
	binTree *p;
	p=new binTree;
	Count++;
	p->n=Count;
	if (N>1) {
		p->p1=makeTree(N-1);
		p->p2=makeTree(N-1);
	}
	return p;
}
//Функция освобождения памяти
void fDel(binTree *w){
	if ((w->n)>0) {
		fDel(w->p1);
		fDel(w->p2);
		}
	delete w;
	}

int main()
{
//указатель на начальный элемент дерева
	binTree *q;
//создание 4-уровневого бинарного дерева
	q=makeTree(4);

	cout<<q->n<<endl;
	cout<<q->p2->p1->n<<endl;
	fDel(q);
	cout<<q->p2->p1->n<<endl;
	getch();
	return 0;
}

Последний раз редактировалось perceptron2013; 06.11.2012 в 12:33.
perceptron2013 вне форума Ответить с цитированием
Старый 06.11.2012, 15:58   #2
pu4koff
Старожил
 
Аватар для pu4koff
 
Регистрация: 22.05.2007
Сообщений: 9,091
По умолчанию

Что значит не получается? Синтаксически всё верно, а вот идеологически... Должно всё удаляться, в общем, по идее.
Код:
//функция создания бинарного дерева
binTree *makeTree(int N){
	binTree *p;
	p=new binTree;
	Count++;
	p->n=Count;
	if (N>1) {
		p->p1=makeTree(N-1);
		p->p2=makeTree(N-1);
	}
	else { // Не забываем инициализировать указатели значением NULL, т.к. это потенциальная ошибка для последующего доступа к памяти и утечки её любимой
		p->p1=NULL;
		p->p2=NULL;}
	return p;
}
//Функция освобождения памяти
void fDel(binTree *w){
	if (w == NULL) // Если удалять нечего, то выходим от греха подальше
		return;
	fDel(w->p1);
	fDel(w->p2);
	
	delete w;
	}
Если имеется ввиду, что после удаления всё равно всё выводится нормально, то это просто удачный "мусор" получается. Память при удалении не обнуляется и ничем не заполняется, указатели тут до удаления и после так же остаются одинаковы. По "случайному" стечению обстоятельств не происходит ошибки чтения и всё хорошо. Можете в функции удаления исковеркать значение n или просто пошагово в отладчике пройтись, посмотреть какие строки в какой последовательности отрабатывают.
pu4koff вне форума Ответить с цитированием
Старый 06.11.2012, 16:11   #3
sVasilich
Форумчанин
 
Аватар для sVasilich
 
Регистрация: 16.12.2009
Сообщений: 224
По умолчанию

Возможно, в функции fDel стоит сделать так:

Код:
delete w;
w = NULL;
Это избавит от возможности вывода "удачного" мусора.
Люди бывают 10 типов: те, кто понимают двоичную систему счисления, и те, кто не понимают...
sVasilich вне форума Ответить с цитированием
Старый 06.11.2012, 16:15   #4
pu4koff
Старожил
 
Аватар для pu4koff
 
Регистрация: 22.05.2007
Сообщений: 9,091
По умолчанию

Цитата:
Сообщение от sVasilich Посмотреть сообщение
Возможно, в функции fDel стоит сделать так:

Код:
delete w;
w = NULL;
Это избавит от возможности вывода "удачного" мусора.
В данном случае не избавит. Данное значение не выйдет никуда из функции fDel, потому как там передаётся указатель по значению.
Если нужно, чтобы NULL возвращался на уровень выше, то нужно передавать указатель по указателю, т.е. void fDel(binTree **w);
Эта запись по сути даёт только возможность последующей проверки на w == NULL и не более того.
pu4koff вне форума Ответить с цитированием
Старый 06.11.2012, 16:28   #5
sVasilich
Форумчанин
 
Аватар для sVasilich
 
Регистрация: 16.12.2009
Сообщений: 224
По умолчанию

На счёт передачи по значению, недосмотрел, спасибо.

Цитата:
Эта запись по сути даёт только возможность последующей проверки на w == NULL и не более того.
Такой код (qt, компилятор gcc)

Код:
int* p = new int(1);
delete p;
qDebug()<<*p;
печатает 0 (т.е. попадает в неопределённость), а такой

Код:
int* p = new int(1);
delete p;
p = NULL;
qDebug()<<*p;
ругается на Segmentation fault, т.е. не даёт разименовать и позволяет быстрее найти ошибку. С этой точки зрения советовал
Люди бывают 10 типов: те, кто понимают двоичную систему счисления, и те, кто не понимают...

Последний раз редактировалось sVasilich; 06.11.2012 в 16:30.
sVasilich вне форума Ответить с цитированием
Ответ


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

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

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


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Указатель на родителя в бинарном дереве Green Gin Общие вопросы C/C++ 8 01.04.2012 18:14
удаление элемента в бинарном дереве Kukurudza Общие вопросы C/C++ 1 26.06.2011 22:51
Расчет уровней в бинарном дереве holi10 Общие вопросы C/C++ 0 01.06.2011 18:22
Поиск в бинарном дереве не по ключу lebrosha Помощь студентам 2 26.05.2009 15:32
Удаление вершины в бинарном дереве lebrosha Помощь студентам 2 24.05.2009 13:51