Пак нишки (memory leak)
2 отговора
109 прегледа
Пак нишки (memory leak)
Пак нишки (memory leak)
Създвам си някакъв наследник на tThread, който в конструтора си прави нещо и установява някакъв флаг (допълнително пропърти).
Нишката не се стартира при създаване (CreateSuspended=true)
Малко след това проверявам флага и ако не ми харесва, не стартирам нишката, а я унищожавам с FreeAndNil.
Е, според MemCheck, така ми се губят 8 байта в:
Ако си стартирам нишката и си я унищожа,
когато си свърши работата (пак с FreeAndNil),
всичко е ОК.
Мисля си, че това P се ползва при създаване и в някой момент делфито го освобождава, но аз не го оставям да стигне до тоя момент (унищожавам му притежателя предварително)
Та ако има забележки, идеи и всякакви предложения - ще съм благодарен пак :)
ПП
Нормално си минава през всички деструтори и заетата от мен памет си се освобождава - както е видно и от мястото на memory leak-a
Създвам си някакъв наследник на tThread, който в конструтора си прави нещо и установява някакъв флаг (допълнително пропърти).
Нишката не се стартира при създаване (CreateSuspended=true)
Малко след това проверявам флага и ако не ми харесва, не стартирам нишката, а я унищожавам с FreeAndNil.
Е, според MemCheck, така ми се губят 8 байта в:
Unit Systems
function BeginThread(SecurityAttributes: Pointer; StackSize: LongWord;
ThreadFunc: TThreadFunc; Parameter: Pointer; CreationFlags: LongWord;
var ThreadId: LongWord): Integer;
var
P: PThreadRec;
begin
New(P); /////// ЕТО ТУКА !!!!!!!!!!!!!!!
P.Func := ThreadFunc;
P.Parameter := Parameter;
IsMultiThread := TRUE;
Result := CreateThread(SecurityAttributes, StackSize, @ThreadWrapper, P,
CreationFlags, ThreadID);
end;
Ако си стартирам нишката и си я унищожа,
когато си свърши работата (пак с FreeAndNil),
всичко е ОК.
Мисля си, че това P се ползва при създаване и в някой момент делфито го освобождава, но аз не го оставям да стигне до тоя момент (унищожавам му притежателя предварително)
Та ако има забележки, идеи и всякакви предложения - ще съм благодарен пак :)
ПП
Нормално си минава през всички деструтори и заетата от мен памет си се освобождава - както е видно и от мястото на memory leak-a
Редактирано от NikB на
Re: Пак нишки (memory leak)
Разгледай функцията ThreadWrapper в същия unit. Това P (LPVOID lpParameter според MSDN) се подава като единствен параметър на функцията LPTHREAD_START_ROUTINE lpStartAddress (в случая ThreadWrapper) и тя вероятно го освбождава накрая. При стартиране на нишката се изпълнява тази функция, а тя вика execute на нишката ти.
Ако наистина ThreadWrapper унищожава record-a, значи може би си открил проблем в Delphi, защото ThreadWrapper няма да се изпълни, ако унищожиш нишката преди да си я пуснал.
Сега се сещам, че не е ясно какво означава "унищожавам", т.е. трябва да се види и какво прави TThread.Free.
Ако разбереш каква е работата, кажи и на нас, защото е интересно.
Ако наистина ThreadWrapper унищожава record-a, значи може би си открил проблем в Delphi, защото ThreadWrapper няма да се изпълни, ако унищожиш нишката преди да си я пуснал.
Сега се сещам, че не е ясно какво означава "унищожавам", т.е. трябва да се види и какво прави TThread.Free.
Ако разбереш каква е работата, кажи и на нас, защото е интересно.
Поразгледах, май концепцията ми е крива :)
Поразгледах, май концепцията ми (създаване на нишка, която може да не се стартира) е крива :)
Може би трябва да сменя подхода и да избера някой от следните подходи:
1) Предварително да проверявам условията и ако не ми харесат, въобще да не създавам нишка
2) Да създавм нишката винаги, а в execute-то й да проверявам условията и ако не са OK, да прескачам цялото тяло на метода execute и да завършвам работа.
ПП За сведение:
Може би трябва да сменя подхода и да избера някой от следните подходи:
1) Предварително да проверявам условията и ако не ми харесат, въобще да не създавам нишка
2) Да създавм нишката винаги, а в execute-то й да проверявам условията и ако не са OK, да прескачам цялото тяло на метода execute и да завършвам работа.
ПП За сведение:
destructor TThread.Destroy;
begin
if not FFinished and not Suspended then
begin
Terminate;
WaitFor;
end;
if FHandle <> 0 then CloseHandle(FHandle);
inherited Destroy;
RemoveThread;
end;
procedure RemoveThread;
begin
EnterCriticalSection(ThreadLock);
try
if ThreadCount = 1 then
PostMessage(ThreadWindow, CM_DESTROYWINDOW, 0, 0);
finally
LeaveCriticalSection(ThreadLock);
end;
end;