我一直在試圖追查內存泄漏絕地VCL的JvHidControllerClass.pas
,這是我在源歷史上遇到了這個變化:德爾福:一個線程是否應該被創建爲「不被掛起」?
一修訂:
constructor TJvHidDeviceReadThread.CtlCreate(const Dev: TJvHidDevice);
begin
inherited Create(True);
Device := Dev;
NumBytesRead := 0;
SetLength(Report, Dev.Caps.InputReportByteLength);
end;
當前版本:
constructor TJvHidDeviceReadThread.CtlCreate(const Dev: TJvHidDevice);
begin
inherited Create(False);
Device := Dev;
NumBytesRead := 0;
SetLength(Report, Dev.Caps.InputReportByteLength);
end;
從經驗,我發現,如果你創建一個線程不是暫停:
inherited Create(False);
然後線程立即開始運行。在這種情況下,它會嘗試訪問尚未初始化的對象:
procedure TJvHidDeviceReadThread.Execute;
begin
while not Terminated do
begin
FillChar(Report[0], Device.Caps.InputReportByteLength, #0);
if Device.ReadFileEx(Report[0], Device.Caps.InputReportByteLength, @DummyReadCompletion) then
馬上試圖填補Report
,並訪問對象Device
。問題是他們還沒有初始化;這些都是未來行線程開始後:
Device := Dev;
NumBytesRead := 0;
SetLength(Report, Dev.Caps.InputReportByteLength);
我意識到這是一個競爭條件;而且用戶在生產中遇到崩潰的機率很低,所以離開比賽崩潰可能是無害的。
但我在路上嗎?我錯過了什麼嗎?請撥打:
BeginThread(nil, 0, @ThreadProc, Pointer(Self), Flags, FThreadID);
不啓動線程並立即運行?這是否真的是(故意)添加到JVCL的競態條件迴歸?是否有關於
CreateSuspended(False);
一些祕密,使得它的正確代碼過來:
CreateSuspended(True);
...
FDataThread.Resume;
?
被誤調用
TMyThread.Create(False)
我已提起訴訟,它在我的大腦從未正確的已被燒燬後。是否有任何有效的用法讓線程立即啓動(當你需要初始化值時)?
哇! JVCL D5!我雖然在我退出後關閉了它,並停止保持D5兼容性。這種懷舊的感覺... –
@ Arioch'The不要太懷舊;它是從2009年開始的JVCL 3.x。嚴格來說,這是Richard Marquand從2005年開始的最初HidController類;我幫了一些忙。 JVCL採用的版本經歷了巨大的*「jcl-ifying」*;但沒有真正的差異;但從技術上說,我使用理查德的版本;所以我可以修復FastMM捕獲的* free-after-free *崩潰。 –