Освобождение памяти, утечка памяти
Привожу код, если кому не в лом будет посмотреть - прошу помочь и сказать почему не освобождается память из под объекта.
//Данный класс является базовым классом для представления ХТМЛ тага.
//Конструктор:
// THtmlTag(IHTMLDocument2* pDoc) - Конструктор для создания базового элемента ROOT
// THtmlTag(IHTMLElement *pElem,THtmlTag *ParentTag) - Конструктор для создания любых других элементов
//Свойства:
// Name - Название тага
// Text - Текст который содержит таг
// TagInterface - Указатель на СОМ-интерфэйс этого тага в ИнтернетЭксплорере
// ChildTagsCount - Количество дочерних тагов
// Parent - Указатель на объект этого же класса, являющийся родителем для этого объекта
// ChildTags - Массив указателей на дочерние объекты.
//Методы:
// Free - Удаляет объект и все его дочерние объекты из памяти.
// ToTreeView - воспроизводит древовидную структуру всех дочерних объектов и выводит ее в дерево.
//Примечания:
// Каждому объекту класса ставится в соответствие таг в ХТМЛ документе, для парсинга документа
// используется внутренний парсер интернет-эксплорера (ИЕ), структура документа представляет собой
// древовидную структуру. Соответственно, т.к. у каждого тага есть область действия и все таги,
// что лежат в этой области действия считаются дочерними для этого тага, эта структура и отражена
// в объектах данного класса. Для более подробного представления структуры ХТМЛ документа см. материалы
// по DOM (Data Object Model) MS DHTML. Для доступа к механизмам парсинга ИЕ используются
// интерфэйсы СОМ-объектов которые предоставляет ИЕ. Указателем на такой элемент в классе явлется
// член свойство объекта TagInterface.
//==============================================================================
//------------------------------------------------------------------------------
class THtmlTag
{
private:
//-------------------------Закрытые свойства объека-------------------------//
//-------------------------Закрытые методы объека---------------------------//
// Описания даны в файле реализации
void __fastcall ToTreeViewRecursion(THtmlTag *Tag,TTreeView * HtmlTree, TTreeNode *TreeNode, bool DisplayName, bool DisplayText,bool DisplayLink, AnsiString Delimeter);
//--------------------------------------------------------------------------//
public:
//------------------------- Открытые свойства объека------------------------//
AnsiString Name; //Название тага
AnsiString Text; //Текст который содержит таг
TStringList *Links; //Ссылки которые содержит таг
IHTMLElement *TagInterface; //Указатель на СОМ-интерфэйс этого тага в ИнтернетЭксплорере
long ChildTagsCount; //Количество дочерних тагов
THtmlTag *Parent; //Указатель на объект этого же класса, являющийся родителем для этого объекта
THtmlTag **ChildTags; //Массив указателей на дочерние объекты.
//------------------------- Открытые методы объека--------------------------//
// Описания даны в файле реализации
__fastcall THtmlTag(IHTMLDocument2* pDoc);
__fastcall THtmlTag(IHTMLElement *pElem,THtmlTag *ParentTag);
void __fastcall Free();
void __fastcall ToTreeView(TTreeView *TreeView,bool DisplayName, bool DisplayText,bool DisplayLink, AnsiString Delimeter);
//--------------------------------------------------------------------------//
};
//-------------И самое главное метод Free()--------------
//---------------------------------------------------------------------------
void __fastcall THtmlTag::Free()
{
try
{
for (int i = 0; i < this->ChildTagsCount; i++)
this->ChildTags->Free();
if (this->TagInterface!=NULL)
this->TagInterface->Release();
Links->Free();
delete[] ChildTags;
delete this;
}
catch(...)
{;}
}
//---------------------------------------------------------------------------
// Тип:
// Конструктор
// Принадлежность:
// Класс THtmlTag
// Доступ:
// Открытый
// Что делает:
// Конструктор класса, для создания объекта класса на основе интерфэйса СОМ
// объекта интернет-эксплорера IHTMLElement.
// Параметры:
// 1) IHTMLElement *pElem - Указатель на СОМ- интерфэйс
// 2) THtmlTag *ParentTag - Указатель на родительский объект этого же класса
// если элемент создается как первый элемент а не как чей-то потомок передается значение NULL
// Возвращаемое значение:
// Указатель на созданный объект.
__fastcall THtmlTag::THtmlTag(IHTMLElement *pElem,THtmlTag *ParentTag)
{
Name = "UNKNOWNTAG";
Text = "";
Parent = ParentTag;
TagInterface = pElem;
Links = new TStringList();
AnsiString Link;
BSTR wsName, wsText;
Variant vLink;
vLink.Empty();
WideString wsAttributeName = "href";
pElem->get_tagName(&wsName);
pElem->get_innerText(&wsText);
pElem->getAttribute(wsAttributeName.c_bstr(),0,vLink);
if(wsName)
{
Name = wsName;
}
if(wsText)
{
Text = wsText;
}
try
{
Link = VarToStr(vLink);
Links->Add(Link);
}
catch(...)
{;}
SysFreeString(wsName);
SysFreeString(wsText);
//------
IDispatch *IDispChildren, *IDispChild;
IHTMLElementCollection * ICollChildren;
IHTMLElement *ChildElement;
TagInterface->get_children(&IDispChildren);
IDispChildren->QueryInterface(IID_IHTMLElementCollection,(void**) &ICollChildren );
if(SUCCEEDED(ICollChildren->get_length(&ChildTagsCount)))
{
ChildTags = (THtmlTag **)malloc(sizeof(THtmlTag)*ChildTagsCount);
for(long j = 0; j <ChildTagsCount; j++)
{
ICollChildren->item(TVariant(j), TVariant(0), &IDispChild);
if(SUCCEEDED(IDispChild->QueryInterface(IID_IHTMLElement, (void**) &ChildElement)))
{
if (ChildElement==NULL)
continue;
ChildTags[j] = new THtmlTag(ChildElement, this);
}
}
}
IDispChildren->Release();
ICollChildren->Release();
//------
}
//---------------------------------------------------------------------------
// Тип:
// Конструктор
// Принадлежность:
// Класс THtmlTag
// Доступ:
// Открытый
// Что делает:
// Конструктор класса, для создания объекта класса на основе интерфэйса СОМ
// объекта интернет-эксплорера IHTMLDocument2.
// Параметры:
// 1) IHTMLDocument2* pDoc - Указатель на СОМ- интерфэйс
// Возвращаемое значение:
// Указатель на созданный объект.
// Примечание:
// Данным конструктором создается объект ROOT который не соответствует никакому тагу
// в документе но является корнем древовидной структуры объектов. Самый старший таг в документе
// <HTML> таг, но если вдруг в документе есть еще таги того же уровня (например коментарии в начале страницы)
// то чтобы не упускать их из поля зрения все они помещаются как дочерние в объект ROOТ.
__fastcall THtmlTag::THtmlTag(IHTMLDocument2* pDoc)
{
Name = "ROOT";
Text = "";
Parent = NULL;
TagInterface = NULL;
Links = new TStringList();
IHTMLElementCollection * pElemColl;
if(SUCCEEDED(pDoc->get_all(&pElemColl)))
{
long Count;
IHTMLElement *pElem, *pParentElem;
TList *List = new TList();
IDispatch *pmDisp;
if(SUCCEEDED(pElemColl->get_length(&Count)))
for(long i = 0; i < Count; i++)
{
pElemColl->item(TVariant(i), TVariant(0), &pmDisp);
if(SUCCEEDED(pmDisp->QueryInterface(IID_IHTMLElement, (void**) &pElem)))
{
pElem->get_parentElement(&pParentElem);
if (pParentElem==NULL)
List->Add(pElem);
}
}
ChildTagsCount = List->Count;
ChildTags = (THtmlTag **)malloc(sizeof(THtmlTag)*ChildTagsCount);
for(long i = 0; i < ChildTagsCount; i++)
{
ChildTags = new THtmlTag(((IHTMLElement *)List->Items), this);
}
List->Free();
pParentElem->Release();
pmDisp->Release();
pElemColl->Release();
}
}
Всем , доброе время суток. Сделал класс с помощью которого можно HTML-документ представить ввиде дерева, передаешь ему указатель на ком интерфэйс этого документа из TCppWebBrowser и он создает в памяти древовидную структуру из тагов этого документа.
Привожу код, если кому не в лом будет посмотреть - прошу помочь и сказать почему не освобождается память из под объекта.
Я что - то не увидел где метод фрее вызывается. Может его в деструктор сунуть?
Free();
}
//И здесь я бы пользовал new либо уж тогда не delete а free()
ChildTags = (THtmlTag **)malloc(sizeof(THtmlTag)*ChildTagsCount);
Я что - то не увидел где метод фрее вызывается. Может его в деструктор сунуть?
Free();
}
//И здесь я бы пользовал new либо уж тогда не delete а free()
ChildTags = (THtmlTag **)malloc(sizeof(THtmlTag)*ChildTagsCount);
Без разницы, что free() что delete и так и так не освобождается.
Метод Free() вызывается в основном тексте программы. Деструктор насколько я понимаю вызывается перед тем как удалить объект из памяти т.е. перед delete this в методе Free(), так что если вызвать фри из деструктора, то будет рекурентное зацикливание (фри вызывает деструктор, деструктор вызывает фри) или я ошибаюсь?
Без разницы, что free() что delete и так и так не освобождается.
Метод Free() вызывается в основном тексте программы. Деструктор насколько я понимаю вызывается перед тем как удалить объект из памяти т.е. перед delete this в методе Free(), так что если вызвать фри из деструктора, то будет рекурентное зацикливание (фри вызывает деструктор, деструктор вызывает фри) или я ошибаюсь?
На сколько я знаю, но могу и ошибаться
p_MyClass = (MyClass*)malloc(sizeof(MyClass));
delete p_MyClass; //очищается только указатель, а распределенна память не убирается
//а вот если
MyClass* p_MyClass;
p_MyClass = new MyClass;
delete p_MyClass; //должно сработать
Что касается деструктора, то предложение такое:
Не лопатить весь список, а удалять только свой эл - т. По идее всю рекурсию delete сам отработает.
На сколько я знаю, но могу и ошибаться
p_MyClass = (MyClass*)malloc(sizeof(MyClass));
delete p_MyClass; //очищается только указатель, а распределенна память не убирается
//а вот если
MyClass* p_MyClass;
p_MyClass = new MyClass;
delete p_MyClass; //должно сработать
Что касается деструктора, то предложение такое:
Не лопатить весь список, а удалять только свой эл - т. По идее всю рекурсию delete сам отработает.
Интересно как будет выглядеть объявление с помощью new если создается массив указателей на объекты т.е. MyClass** pp_MyClass;
вот так? :
int ElemCount = 10;
pp_MyClass = new MyClass[ElemCount]; //тут он ругнется что не знает квадратных скобок.
for (int i = 0; i < ElemCount; i++)
pp_MyClass = new MyClass(ConstructorParam);
Интересно как будет выглядеть объявление с помощью new если создается массив указателей на объекты т.е. MyClass** pp_MyClass;
вот так? :
int ElemCount = 10;
pp_MyClass = new MyClass[ElemCount]; //тут он ругнется что не знает квадратных скобок.
for (int i = 0; i < ElemCount; i++)
pp_MyClass = new MyClass(ConstructorParam);
Я думаю, что
pp_MyClass = new MyClass()[ElemCount]; //тут он ругнется что не знает квадратных скобок.
for (int i = 0; i < ElemCount; i++)
pp_MyClass = new MyClass(ConstructorParam);
Я думаю, что
pp_MyClass = new MyClass()[ElemCount]; //тут он ругнется что не знает квадратных скобок.
for (int i = 0; i < ElemCount; i++)
pp_MyClass = new MyClass(ConstructorParam);
Спасибо, попробую сделать new\delete -ом о результатах завтра доложу =)