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

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

Вернуться   Форум программистов > Delphi программирование > Работа с сетью в Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

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

Ответ
 
Опции темы Поиск в этой теме
Старый 26.11.2010, 12:36   #1
FReeZ777
 
Регистрация: 26.11.2010
Сообщений: 7
Печаль Непонятная утечка памяти

Здравстуйте, уважаемые формучане!
Написал программу, все работает, но через определенное время (часа 2) выскакивает "External error". Смотрю в диспетчере - процесс съел около гигабайта оперативной памяти.
Суть программы - грузит из файлов данные, заходит через Webbrowser на страницы, отправляет нужную информацию, и так все в цикле.
Данные грузятся из файлов через Tstringlist, после отправки в нужное место очищается с помощью Free.
Вроде бы все окей, но память утекает как вода.
Код:
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls,URLMon, ComCtrls, math, OleCtrls, SHDocVw, ExtCtrls;

type
  TForm1 = class(TForm)
    start: TButton;
    GroupBox1: TGroupBox;
    ScrollBox1: TScrollBox;
    ComboBox1: TComboBox;
    Label1: TLabel;
    back: TButton;
    forward: TButton;
    update: TButton;
    stop: TButton;
    Label2: TLabel;
    Button6: TButton;
    Button7: TButton;
    Label3: TLabel;
    Edit1: TEdit;
    Button8: TButton;
    Button10: TButton;
    ComboBox2: TComboBox;
    Button1: TButton;
    Edit2: TEdit;
    webbrowser1:TWEbbrowser;
    procedure ComboBox1KeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure stopClick(Sender: TObject);
    procedure updateClick(Sender: TObject);
    procedure forwardClick(Sender: TObject);
    procedure backClick(Sender: TObject);
    procedure startClick(Sender: TObject);
    procedure main();
    procedure load();
    procedure Button7Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure Button6Click(Sender: TObject);
    procedure Button8Click(Sender: TObject);
    procedure ComboBox2KeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure auth();
    procedure ComboBox2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button10Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  l,l1,l2,l5,m,jou,get,get1:tstringlist;
  a,y,c,key,st,gg1,doc,tt1:string;
  n,i,id,num,id1,ppp,t,gg,form,k,kat,kall,on:integer;

implementation
<Левый код>
</ Левый код>

procedure Tform1.auth();
begin
WebBrowser1.Navigate('сайт.ком');
while   WebBrowser1.ReadyState <> 4 do
begin
Application.ProcessMessages();
end;
 try
 WebBrowser1.OleObject.Document.All.Tags('input').Item(2).click   ;
 except
 startClick(self);
 end;
Delay(3000);
while   WebBrowser1.ReadyState <> 4 do
begin
Application.ProcessMessages();
end;
WebBrowser1.OleObject.Document.All.Tags('input').Item(1).Value:=tt1;
WebBrowser1.OleObject.Document.All.Tags('input').Item(2).Value:='1627911';
WebBrowser1.OleObject.Document.All.Tags('input').Item(4).Click();
WebBrowser1.OleObject.Document.All.Tags('input').Item(3).Click();
end;

procedure TForm1.startClick(Sender: TObject);
begin
 main();
end;\

procedure Tform1.main();
var ovElements: OleVariant;
     i: Integer;
begin
kall:=1;
webbrowser1.Silent:=true;
l:=tstringlist.create;
l.LoadFromFile('links.txt');
l2:=tstringlist.create;
l2.loadfromfile('last.txt');
gg1:=l2[0];
l1:=tstringlist.create;
l1.loadfromfile('rev/base'+gg1+'.txt');
t:=strtoint(l2[1]);
if t mod 100 = 0 then
begin
Application.ProcessMessages();
while WebBrowser1.ReadyState <> 4 do
begin
Application.ProcessMessages();
end;
try
m:=tstringlist.create;
m.loadfromfile('ttt.txt');
l5:=tstringlist.Create;
l5.loadfromfile('get.txt');
tt1:=m[strtoint(l5[0])];
auth();
if strtoint(l5[0])=m.Count-1 then
begin
l5[0]:=inttostr(0);
end else
l5[0]:=inttostr(strtoint(l5[0])+1);
finally
l5.savetofile('get.txt');
l5.Clear;
l5.Free;
m.clear;
m.free;
end;
delay(4000);
while WebBrowser1.ReadyState <> 4 do
begin
Application.ProcessMessages();
end;
load();
end else
load();
end;

procedure TForm1.load();
var ovElements: OleVariant;
     i: Integer;
begin
try
while   WebBrowser1.ReadyState <> 4 do
begin
Application.ProcessMessages();
end;
WebBrowser1.Navigate(l1[t]+'сайт');
//label1.caption:='Òåêóùèé æóðíàë: ' +l1[strtoint(l2[1])];
//label2.caption:='Òåêóùàÿ áàçà:'+l2[0];
// label2.caption:='Íîìåð æóðíàëà â äàííîé áàçå:'+l2[1];
label5.caption:='Òåêóùèé æóðíàë # '+inttostr(t);
edit2.text:=l1[t];
if t=l1.count-1 then
begin
gg1:=inttostr(strtoint(gg1)+1);
t:=0;
end;
t:=t+1;
l2[1]:=inttostr(t);
l2.savetofile('last.txt');
delay(500);
while   WebBrowser1.ReadyState <> 4 do
begin
Application.ProcessMessages();
end;
<Левый код>
</Левый код>
while   WebBrowser1.ReadyState <> 4 do
begin
Application.ProcessMessages();
end;
finally
l1.Clear;
l1.Free;
l2.Clear;
l2.Free;
l.Clear;
l.Free;
end;
if on<>1 then 
main();
end;
end;

end.
Пожалуйста, помогите!

Последний раз редактировалось mihali4; 26.11.2010 в 12:44.
FReeZ777 вне форума Ответить с цитированием
Старый 26.11.2010, 12:54   #2
mihali4
*
Старожил
 
Регистрация: 22.11.2006
Сообщений: 9,201
По умолчанию

Цитата:
Сообщение от FReeZ777 Посмотреть сообщение
Вроде бы все окей, но память утекает как вода.
Так немудрено... Никакого окея не наблюдается.
У вас из TForm1.load вызывается Tform1.main, в которой вновь и вновь создаются экземпляры
Код:
l:=tstringlist.create;
...
l2:=tstringlist.create;
...
l1:=tstringlist.create;
которые не освобождаются.
Вот они и наапливаются, неосвобожденные...
Перенесите их создание и освобождение в startClick(Sender: TObject);
mihali4 вне форума Ответить с цитированием
Старый 27.11.2010, 11:39   #3
FReeZ777
 
Регистрация: 26.11.2010
Сообщений: 7
По умолчанию

Согласен с вами, Main вызывается из Load, но ведь из main затем снова load вызывается, которая содержит строки
l.free
l1.free,
которая, по идее, должна убивать созданные в main Tstringlist'ы.
Создать Tstringlist'ы в startclick - это сейчас попробую, однако все же интересно, почему так происходит, или все-таки я чего-то недопонимаю в логике своей же программы.
____
Попробовал убрать Tstringlist.create в start.click - ничего не помогло!
память как утекает, так и утекает. Мистика какая то.
Может быть, это все-таки Twebbrowser не осовобождает память из под чего-то?

Последний раз редактировалось FReeZ777; 27.11.2010 в 12:27.
FReeZ777 вне форума Ответить с цитированием
Старый 27.11.2010, 16:25   #4
mihali4
*
Старожил
 
Регистрация: 22.11.2006
Сообщений: 9,201
По умолчанию

Попробуйте закомментировать содержимое процедуры Load, чтобы она просто ничего не делала.
И погоняйте...
mihali4 вне форума Ответить с цитированием
Старый 27.11.2010, 16:53   #5
FReeZ777
 
Регистрация: 26.11.2010
Сообщений: 7
По умолчанию

Сделал как сказали, все так же, только память грузится еще быстрее.
Вообще непонятно, ведь Stringlistы создаются только один раз при клике на кнопку а потом в них только циклично грузятся из файла данные.
По идее содержимое Stringlistа должно заменяться вновь загруженным файлом, я даже на всякий случай перед каждой новой загрузкой добавлял:
l.clear;
дабы очистить предыдущий лист, если там что-то осталось, но ничего не помогло.
Я скоро свихнусь.
FReeZ777 вне форума Ответить с цитированием
Старый 28.11.2010, 00:20   #6
FReeZ777
 
Регистрация: 26.11.2010
Сообщений: 7
Печаль

Методом экспериментов пришел к тому, что Tstringlist тут вообще ни причём
Память грузит все-таки Twebbrowser.
При цикличном серфинге по страничкам память неумолимо растет.
Динамическое создание и освобождение webbrowser'а не дает никакого эффекта
вот что нарыл по этому поводу:
Цитата:
Первым делом это TWebBrowser.Document:IDispatch . Через это свойство можно получить доступ к интерфейсу IHtmlDocument2.. Далее через этот интерфейс можно получить доступ к большинству средств по взаимодействию с загруженным документом. То есть это очень интересное и "нужное" свойство. Но немного забегая наперед, скажу, что если Вы попытаетесь использовать TWebBrowser.Document:IDispatch, то Вы рано или поздно заметите довольно странную "утечку" памяти в процессе навигации. В чем же дело? После анализа ситуации, удалось определить, что для любой интерфейсной ссылки на документ, которая получена через этот свойство, счетчик использования "необоснованно" увеличивается на 1 и соответствующий COM-обьект никогда не будет освобожден. При более детальном изучении нашлась и создательница этой проблемы - function TOleControl.GetIDispatchProp(Index: Integer): IDispatch;, через которую и работает TWebBrowser.Document:IDispatch (я речь веду о Delphi5, возможно в Delphi4 все нормально, не проверял). Детальный рассказ об этой ситуации выходит за рамки этой статьи..
К счастью эту проблему легко обойти, использовав для получения IHtmlDocument2 альтернативные возможности, хотя бы WebBrowser1.ControlInterface.Docume nt .

Также хочется упомянуть о property LocationURL: WideString; Как утверждается в вышеупомянутой статье Александра Лозовюка , оно содержит URL ресурса, загруженного в браузер. Того же мнения придерживается и контекстная справка от Delphi5. Мало того - об этом также говорится в MSDN . - во всяком случае так было на момент написания статьи ...
Ничего не пойму в этом, пожалуйста, помогите кто чем может
FReeZ777 вне форума Ответить с цитированием
Старый 28.11.2010, 00:31   #7
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

не вижу чтоб вы использовали интерфейс IDispatch.
так что не то вы нашли, но вообще такой вопрос, вам зачем нужен WB?
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 28.11.2010, 00:38   #8
mihali4
*
Старожил
 
Регистрация: 22.11.2006
Сообщений: 9,201
По умолчанию

Да вроде бы по-русски написано, что нужно использовать WebBrowser1.ControlInterface.Docume nt вместо WebBrowser1.OleObject.Document...
Можете сами погуглить по "дельфи Twebbrowser утечки памяти", там люди именно об этом говорят, как о единственном способе борьбы.
mihali4 вне форума Ответить с цитированием
Старый 28.11.2010, 00:42   #9
FReeZ777
 
Регистрация: 26.11.2010
Сообщений: 7
По умолчанию

Webbrowser нужен для цикличного серфинга страниц
принцип.
Грузим страницу>заполняем там нужные формы>грузим следующую страницу
и так далее
FReeZ777 вне форума Ответить с цитированием
Старый 28.11.2010, 00:44   #10
FReeZ777
 
Регистрация: 26.11.2010
Сообщений: 7
По умолчанию

Цитата:
Сообщение от mihali4 Посмотреть сообщение
Да вроде бы по-русски написано, что нужно использовать WebBrowser1.ControlInterface.Docume nt вместо WebBrowser1.OleObject.Document...
Можете сами погуглить по "дельфи Twebbrowser утечки памяти", там люди именно об этом говорят, как о единственном способе борьбы.
Да гуглил я, гуглил, в том то и дело, что никакой толковой инфы по этому поводу не нашел, поэтому прошу тут
FReeZ777 вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Утечка памяти Juffin Общие вопросы Delphi 3 02.11.2010 12:11
Утечка памяти ZvEr_HaCkEr Свободное общение 13 24.09.2010 19:30
Indy в потоке - утечка памяти PUH Фриланс 5 28.12.2009 14:06
утечка памяти в С++ vengo Общие вопросы C/C++ 9 10.06.2008 21:24
DrawState - утечка памяти? unnamed Win Api 2 11.04.2007 18:36