C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Освобождение памяти!
SomewhereSomeho_
Отправлено: 17.12.2004, 12:40


Не зарегистрирован







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

CODE

//==============================================================================
//Данный класс является базовым классом для представления ХТМЛ тага.
//Конструктор:
//         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[i]->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[i] = new THtmlTag(((IHTMLElement *)List->Items[i]), this);
  }
  List->Free();

  pParentElem->Release();
  pmDisp->Release();
  pElemColl->Release();
 }
}



Bond
Отправлено: 05.01.2005, 11:22


Станционный диспетчер

Группа: Участник
Сообщений: 142



привет. я начал разбираться с кодом, но на это нужно много времени.
а его нету smile.gif вкратце:

1. деструктор вызывается в момент освобождения памяти, которую занимает экземпляр класса, а ты в деструкторе класса просиш экземпляр удалить себя же — неверно. я не пробовал, не знаю что получиться. смотри
CODE
delete this;


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

3. в деструкторе корня дерева удаляй его вложенные элементы

Вернуться в Вопросы программирования в C++Builder