Текущий архив: 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