Jedi 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)
私は決して正しくないので、私の脳にそれをファイルしました。(値を初期化する必要がある場合) スレッドをすぐに開始できる有効な用途はありますか?