Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.03.18;
Скачать: CL | DM;

Вниз

Утечка памяти при работе с потоками   Найти похожие ветки 

 
Loginov Dmitry ©   (2007-02-22 07:59) [0]

Утечка памяти при работе с потоками


 TMyThread = class(TThread)
 private

 protected
   procedure Execute; override;
 public

 end;

........................

procedure TMyThread.Execute;
begin
  FreeOnTerminate := True;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  TMyThread.Create(False).Terminate;
end;


В данном случае деструктор не отработает, так же, как и Execute. Просто у меня такая ситуация, когда в одних условиях поток может работать минутами, а при других входных данных поток может отработать очень быстро, и Execute не успевает выполнится.
Для борьбы с утечкой я перекрыл AfterConstruction и в эту процедуру добавил строку Sleep(300).
Кто нибудь сталкивался с подобным. Как боролись?


 
SlymRO   (2007-02-22 08:14) [1]

FreeOnTerminate := True; нужно делать до Terminate;


 
Сергей М. ©   (2007-02-22 08:15) [2]


> деструктор не отработает


Отработает.


> так же, как и Execute


И Execute отработает.


> Утечка памяти при работе с потоками


Нет здесь никакой утечки.


 
KSergey ©   (2007-02-22 08:18) [3]

> Loginov Dmitry ©   (22.02.07 07:59)  
> а при других входных данных
> поток может отработать очень быстро, и Execute не успевает
> выполнится.


Какой поток? Создаваймый? получается, Execute все же выполнится, раз "поток может отработать"?


 
ЮЮ ©   (2007-02-22 08:19) [4]


>может отработать очень быстро,  и Execute не успевает выполнится


не успевает выполнится - это как? Не успевает вызваться? А для чего он, собственно, создается, если не для выполнения  Execute?
Зчем такой "пример":  TMyThread.Create(False).Terminate;

Set FreeOnTerminate to true if you don’t want to explicitly destroy threads after they finish executing.
а в  TMyThread.Create(False).Terminate; ты не прочь сделать это explicitly.

Утечка то в чем? В том, что убил, не успев выполнить Execute ?


 
KSergey ©   (2007-02-22 08:20) [5]

А вообще у меня всегда создавалось впечатление, что Execute потока начинает работать еще до окончания завершения конструктора дельфийского объекта, если указано TMyThread.Create(False)


 
Сергей М. ©   (2007-02-22 08:23) [6]


> KSergey ©   (22.02.07 08:20) [5]


> у меня всегда создавалось впечатление


Не обязательно, но вполне возможно. Все зависит от того, как системный планировщик потоков распределит кванты времени между потоком, вызвавшим конструктор и потоком, который создается в этом конструкторе.


 
ЮЮ ©   (2007-02-22 08:36) [7]

Terminate sets the thread"s Terminated property to True. If you have implemented the Execute method properly, it checks the Terminated property periodically, and stops execution when Terminated is True.

Да и Terminate  это не унчтожение нити, а выставление флажка, который и следует обрабатывать в Execute. так что от Execute никуда не денешься.


 
KSergey ©   (2007-02-22 08:44) [8]

> ЮЮ ©   (22.02.07 08:36) [7]
> Да и Terminate  это не унчтожение нити, а выставление флажка,

О! точно!
Как я о том не подумал? :(


 
evvcom ©   (2007-02-22 09:22) [9]

> [6] Сергей М. ©   (22.02.07 08:23)
> но вполне возможно

Даже, наверное, очень вероятно. Помню как-то с год или 2 назад была ветка, мы тут все очень горячо спорили. Я накидал эксперимент, где создавалось несколько потоков и менеджер рулил ими через suspend и resume. Хотя нигде и не написано, что при resume управление передается этому потоку, и на это даже Рихтер обращал внимание, но тем не менее именно так и происходило с завидным постоянством. Только отладчик путал эти карты. Вполне вероятно, что и здесь при старте потока управление незамедлительно ему и передается, независимо от оставшихся квантов времени еще работающего потока.


 
Loginov Dmitry ©   (2007-02-22 09:30) [10]

> [2] Сергей М. ©   (22.02.07 08:15)
>
> > деструктор не отработает
>
>
> Отработает.
>
>
> > так же, как и Execute
>
>
> И Execute отработает.
>
>
> > Утечка памяти при работе с потоками
>
>
> Нет здесь никакой утечки.


Проверьте код хотябы.


 
Сергей М. ©   (2007-02-22 09:45) [11]


> Loginov Dmitry ©   (22.02.07 09:30) [10]


Да что его проверять ?

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


 
Loginov Dmitry ©   (2007-02-22 09:50) [12]

Вы тестировали код [0]? Нет? А вот я тестировал. С помощью FastMM4. Этот манагер врать не будет.


 
Сергей М. ©   (2007-02-22 09:53) [13]


> Loginov Dmitry ©   (22.02.07 09:50) [12]


> Этот манагер врать не будет


Угу. И этот "манагер" прямо так и сказал тебе, мол, методы Destroy и Execute не вызываются, так что ли ? Или это отсебячена, основанная на домыслах, а не на фактах ?


 
Loginov Dmitry ©   (2007-02-22 09:58) [14]

> Или это отсебячена, основанная на домыслах, а не на фактах
> ?


Эта "отсебячена" основана на фактах. Проверьте же сами в конце концов.


 
Loginov Dmitry ©   (2007-02-22 10:02) [15]

Перекройте деструктор


destructor TMyThread.Destroy;
begin
  inherited;
  Windows.Beep(500, 100);
end;


Если услышите звучек, то вы по всем статьям меня сделали.


 
Сергей М. ©   (2007-02-22 10:02) [16]


> Loginov Dmitry ©   (22.02.07 09:58) [14]


На каких фактах-то ? Конкретно ?


 
Сергей М. ©   (2007-02-22 10:05) [17]


> Если услышите звучек


Что за детсад со "звучками" ?

Ты про встроенный в Делфи отладчик слышал  ?


 
ЮЮ ©   (2007-02-22 10:09) [18]

function ThreadProc(Thread: TThread): Integer;
var
 FreeThread: Boolean;
begin
{$IFDEF LINUX}
 if Thread.FSuspended then sem_wait(Thread.FCreateSuspendedSem);
{$ENDIF}
 try
   if not Thread.Terminated then
   try

так как Thread уже при создании Terminated, то Execute, естественно, не выполняется

     Thread.Execute;
   except
     Thread.FFatalException := AcquireExceptionObject;
   end;
 finally
   FreeThread := Thread.FFreeOnTerminate;
   Result := Thread.FReturnValue;
   Thread.DoTerminate;
   Thread.FFinished := True;
   SignalSyncEvent;
   if FreeThread then Thread.Free;

 так как FreeOnTerminate = false (Ехесute не вызывался), то  
 Thread.Free не вызывается

{$IFDEF MSWINDOWS}
   EndThread(Result);
{$ENDIF}
{$IFDEF LINUX}
   // Directly call pthread_exit since EndThread will detach the thread causing
   // the pthread_join in TThread.WaitFor to fail.  Also, make sure the EndThreadProc
   // is called just like EndThread would do. EndThreadProc should not return
   // and call pthread_exit itself.
   if Assigned(EndThreadProc) then
     EndThreadProc(Result);
   pthread_exit(Pointer(Result));
{$ENDIF}
 end;
end;


Автору. А чего, собственно, хотел? Thread - это не компонент с палитры для батонокидателей и использовать его надо в сответствии слогикой, в него заложенной.
Сделай или так, чтобы Execute выполнялся, коль ты именно в нем устанавливаешь FreeOnTerminate := True; Или устоанови его в True до Terminate.


 
Сергей М. ©   (2007-02-22 10:16) [19]


> ЮЮ ©   (22.02.07 10:09) [18]


А вот я взял да и установил вызывающему конструктор потоку наинизший приоритет - и в строчке if not Thread.Terminated then условие not Thread.Terminated запросто может быть истинным.


 
ЮЮ ©   (2007-02-22 10:23) [20]


> Сергей М. ©   (22.02.07 10:16) [19]


Ни я ни Автор не додумались, извини :) Доп. потоки вводят чтобы не тормозить основной. А если ему дали  наинизший, вообще зачем с дополнительными возиться?


 
Loginov Dmitry ©   (2007-02-22 10:28) [21]

> Или устоанови его в True до Terminate.


Можно и такой вариант. Приду домой - потестю.


 
ЮЮ ©   (2007-02-22 10:29) [22]

Вы тестировали код [0]? Нет? А вот я тестировал. С помощью FastMM4. Этот манагер врать не будет.

И без FastMM4 видно, что с каждым нажатием Button1 "съёдается" один дескриптор.

Ты про встроенный в Делфи отладчик слышал  ?
Под отладчиком (D7) я и прошел код в [18] и нашел причину утечки - в неправильной готовке кошек.


 
Сергей М. ©   (2007-02-22 10:30) [23]


> ЮЮ ©   (22.02.07 10:23) [20]


Да дело не в этом)
Просто утверждение автора заведомо безапелляционно.
При неких условиях оно истинно, а при иных ложно, и выясняется это с помощью головы и отладчика.


 
ЮЮ ©   (2007-02-22 10:35) [24]


> Просто утверждение автора заведомо безапелляционно.

В обычных условиях оно оказалось истинным. Но исключительно из-за ошибки автора.


 
Loginov Dmitry ©   (2007-02-22 18:02) [25]

> В обычных условиях оно оказалось истинным. Но исключительно
> из-за ошибки автора.


Да. Признаю свою ошибку :(
Просто у нас в колхозе все строчку FreeOnTerminate := True; пихают в Execute, вот и я подумал, что это правильно. Ан нет. Облом!



Страницы: 1 вся ветка

Текущий архив: 2007.03.18;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.059 c
15-1171983453
Gin2
2007-02-20 17:57
2007.03.18
Виндовая писалка


2-1171970778
sashakbest
2007-02-20 14:26
2007.03.18
Памогите, кто знаете


15-1171798982
Чапаев
2007-02-18 14:43
2007.03.18
что для вас иконка в трее (там где часы)?


1-1169637640
_Teddy_
2007-01-24 14:20
2007.03.18
Read error on *.dcu


2-1172578775
Ivolg
2007-02-27 15:19
2007.03.18
Обратная функция