Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

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

385
17 декабря 2004 года
SomewherSomehow
477 / / 25.07.2004
Всем , доброе время суток. Сделал класс с помощью которого можно HTML-документ представить ввиде дерева, передаешь ему указатель на ком интерфэйс этого документа из TCppWebBrowser и он создает в памяти древовидную структуру из тагов этого документа.
Привожу код, если кому не в лом будет посмотреть - прошу помочь и сказать почему не освобождается память из под объекта.


Код:
//==============================================================================
//Данный класс является базовым классом для представления ХТМЛ тага.
//Конструктор:
//         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();
 }
}
259
17 декабря 2004 года
AlexandrVSmirno
1.4K / / 03.12.2004
Цитата:
Originally posted by SomewherSomehow
Всем , доброе время суток. Сделал класс с помощью которого можно HTML-документ представить ввиде дерева, передаешь ему указатель на ком интерфэйс этого документа из TCppWebBrowser и он создает в памяти древовидную структуру из тагов этого документа.
Привожу код, если кому не в лом будет посмотреть - прошу помочь и сказать почему не освобождается память из под объекта.



Я что - то не увидел где метод фрее вызывается. Может его в деструктор сунуть?

 
Код:
void __fastcall THtmlTag::~THtmlTag() {
   Free();
}
//И здесь я бы пользовал new либо уж тогда не  delete а free()
ChildTags = (THtmlTag **)malloc(sizeof(THtmlTag)*ChildTagsCount);
:???:
385
17 декабря 2004 года
SomewherSomehow
477 / / 25.07.2004
Цитата:
Originally posted by AlexandrVSmirno


Я что - то не увидел где метод фрее вызывается. Может его в деструктор сунуть?
 
Код:
void __fastcall THtmlTag::~THtmlTag() {
   Free();
}
//И здесь я бы пользовал new либо уж тогда не  delete а free()
ChildTags = (THtmlTag **)malloc(sizeof(THtmlTag)*ChildTagsCount);
:???:




Без разницы, что free() что delete и так и так не освобождается.
Метод Free() вызывается в основном тексте программы. Деструктор насколько я понимаю вызывается перед тем как удалить объект из памяти т.е. перед delete this в методе Free(), так что если вызвать фри из деструктора, то будет рекурентное зацикливание (фри вызывает деструктор, деструктор вызывает фри) или я ошибаюсь?

259
17 декабря 2004 года
AlexandrVSmirno
1.4K / / 03.12.2004
Цитата:
Originally posted by SomewherSomehow



Без разницы, что free() что delete и так и так не освобождается.
Метод Free() вызывается в основном тексте программы. Деструктор насколько я понимаю вызывается перед тем как удалить объект из памяти т.е. перед delete this в методе Free(), так что если вызвать фри из деструктора, то будет рекурентное зацикливание (фри вызывает деструктор, деструктор вызывает фри) или я ошибаюсь?



На сколько я знаю, но могу и ошибаться

 
Код:
MyClass* p_MyClass;
p_MyClass = (MyClass*)malloc(sizeof(MyClass));
delete p_MyClass; //очищается только указатель, а распределенна память не убирается

//а вот если
MyClass* p_MyClass;
p_MyClass = new MyClass;
delete p_MyClass; //должно сработать


Что касается деструктора, то предложение такое:
Не лопатить весь список, а удалять только свой эл - т. По идее всю рекурсию delete сам отработает.
385
17 декабря 2004 года
SomewherSomehow
477 / / 25.07.2004
Цитата:
Originally posted by AlexandrVSmirno


На сколько я знаю, но могу и ошибаться
 
Код:
MyClass* p_MyClass;
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);

259
17 декабря 2004 года
AlexandrVSmirno
1.4K / / 03.12.2004
Цитата:
Originally posted by SomewherSomehow


Интересно как будет выглядеть объявление с помощью new если создается массив указателей на объекты т.е. MyClass** pp_MyClass;
вот так? :
int ElemCount = 10;
pp_MyClass = new MyClass[ElemCount]; //тут он ругнется что не знает квадратных скобок.
for (int i = 0; i < ElemCount; i++)
pp_MyClass = new MyClass(ConstructorParam);



Я думаю, что

 
Код:
int ElemCount = 10;
pp_MyClass = new MyClass()[ElemCount]; //тут он ругнется что не знает квадратных скобок.
for (int i = 0; i < ElemCount; i++)
  pp_MyClass = new MyClass(ConstructorParam);
385
17 декабря 2004 года
SomewherSomehow
477 / / 25.07.2004
Цитата:
Originally posted by AlexandrVSmirno


Я думаю, что
 
Код:
int ElemCount = 10;
pp_MyClass = new MyClass()[ElemCount]; //тут он ругнется что не знает квадратных скобок.
for (int i = 0; i < ElemCount; i++)
  pp_MyClass = new MyClass(ConstructorParam);



Спасибо, попробую сделать new\delete -ом о результатах завтра доложу =)

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог