Витік пам'яті при роботі з потоками

Витік пам'яті при роботі з потоками


# XA0; TMyThread = class (TThread)
# XA0; private

# XA0; protected
# XA0; # XA0; procedure Execute; override;
# XA0; public

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

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

В даному випадку деструктор не відпрацьована, так само, як і Execute. Просто у мене така ситуація, коли в одних умовах потік може працювати хвилинами, а при інших вхідних даних потік може відпрацювати дуже швидко, і Execute не встигає виконається.
Для боротьби з витоком я перекрив AfterConstruction і в цю процедуру додав рядок Sleep (300).
Хто небудь стикався з подібним. Як боролися?

FreeOnTerminate: = True; потрібно робити до Terminate;


> Деструкцію не відпрацьовані


> Так само, як і Execute

І Execute відпрацює.


> Витік пам'яті при роботі з потоками

Немає тут ніякого витоку.

Який потік? Создаваймий? виходить, Execute все ж виконається, раз "потік може відпрацювати"?


> Може відпрацювати дуже швидко, # XA0; і Execute не встигає виконається

не встигає виконається - це як? Не встигає викликатися? А для чого він, власне, створюється, якщо не для виконання # XA0; Execute?
Зчем такий "приклад": # XA0; TMyThread.Create (False) .Terminate;

Set FreeOnTerminate to true if you do not want to explicitly destroy threads after they finish executing.
а в # XA0; TMyThread.Create (False) .Terminate; ти не проти зробити це explicitly.

Витік то в чому? У тому, що вбив, не встигнувши виконати Execute?

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

Не обов'язково, але цілком можливо. Все залежить від того, як системний планувальник потоків розподілить кванти часу між потоком, що викликав конструктор і потоком, який створюється в цьому конструкторі.

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 # XA0; це не унчтоженіе нитки, а виставляння прапорця, який і слід обробляти в Execute. так що від Execute нікуди не дінешся.

Перевірте код хочаб.

Так що його перевіряти?

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

Ви тестували код [0]? Ні? А ось я тестував. За допомогою FastMM4. Цей манагер брехати не буде.

Угу. І цей "манагер" прямо так і сказав тобі, мовляв, методи Destroy і Execute не викликаються, так чи що. Або це отсебячена, заснована на домислах, а не на фактах?

> Чи це отсебячена, заснована на домислах, а не на фактах
>?

Ця "отсебячена" заснована на фактах. Перевірте ж самі в кінці кінців.


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

На яких фактах щось. Саме?


> Якщо почуєте звучек

Що за дитсадок зі "Звичка"?

Ти про вбудований в Делфі відладчик чув # XA0 ;?

function ThreadProc (Thread: TThread): Integer;
var
# XA0; FreeThread: Boolean;
begin

# XA0; if Thread.FSuspended then sem_wait (Thread.FCreateSuspendedSem);

# XA0; try
# XA0; # XA0; if not Thread.Terminated then
# XA0; # XA0; try

так як Thread вже при створенні Terminated, то Execute, природно, не виконується

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

# XA0, бо на те FreeOnTerminate = false (Ехесute не викликався), то # XA0;
# XA0; Thread.Free не викликається


# XA0; # XA0; EndThread (Result);


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

# XA0; end;
end;

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

> Або устоанові його в True до Terminate.

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

Ви тестували код [0]? Ні? А ось я тестував. За допомогою FastMM4. Цей манагер брехати не буде.

І без FastMM4 видно, що з кожним натисканням Button1 "с'ёдается" один дескриптор.

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

Так. Визнаю свою помилку :(
Просто у нас в колгоспі все рядок FreeOnTerminate: = True; пхають в Execute, ось і я подумав, що це правильно. Але ж ні. Облом!

Схожі статті