đây là ví dụ được tạo. Tôi không muốn đăng mã gốc ở đây. Tôi đã cố gắng trích xuất các phần liên quan.Giao diện, Phương thức ẩn danh và Rò rỉ bộ nhớ
Tôi có giao diện quản lý danh sách người nghe.
TListenerProc = reference to procedure (SomeInt : ISomeInterface);
ISomeInterface = interface
procedure AddListener (Proc : TListenerProc);
end;
Bây giờ tôi đăng ký một người biết lắng nghe:
SomeObj.AddListener (MyListener);
procedure MyListener (SomeInt : ISomeInterface);
begin
ExecuteSynchronized (procedure
begin
DoSomething (SomeInt);
end);
end;
tôi làm được rò rỉ bộ nhớ. Cả hai phương thức nặc danh và các giao diện đều không bao giờ được giải phóng. Tôi nghi ngờ rằng điều này là do một số loại tham chiếu vòng tròn ở đây. Phương thức nặc danh giữ cho alife giao diện và giao diện giữ cho alife ẩn danh.
Hai câu hỏi:
- Bạn có hỗ trợ giải thích điều đó không? Hay tôi còn thiếu cái gì khác ở đây?
- Có điều gì tôi có thể làm được không?
Cảm ơn bạn trước!
EDIT: Đó không phải là dễ dàng như vậy để tái sản xuất này trong một ứng dụng đủ nhỏ để gửi nó ở đây. Điều tốt nhất tôi có thể làm bây giờ là như sau. Phương thức ẩn danh không được phát hành tại đây:
program TestMemLeak;
{$APPTYPE CONSOLE}
uses
Generics.Collections, SysUtils;
type
ISomeInterface = interface;
TListenerProc = reference to procedure (SomeInt : ISomeInterface);
ISomeInterface = interface
['{DB5A336B-3F79-4059-8933-27699203D1B6}']
procedure AddListener (Proc : TListenerProc);
procedure NotifyListeners;
procedure Test;
end;
TSomeInterface = class (TInterfacedObject, ISomeInterface)
strict private
FListeners : TList <TListenerProc>;
protected
procedure AddListener (Proc : TListenerProc);
procedure NotifyListeners;
procedure Test;
public
constructor Create;
destructor Destroy; override;
end;
procedure TSomeInterface.AddListener(Proc: TListenerProc);
begin
FListeners.Add (Proc);
end;
constructor TSomeInterface.Create;
begin
FListeners := TList <TListenerProc>.Create;
end;
destructor TSomeInterface.Destroy;
begin
FreeAndNil (FListeners);
inherited;
end;
procedure TSomeInterface.NotifyListeners;
var
Listener : TListenerProc;
begin
for Listener in FListeners do
Listener (Self);
end;
procedure TSomeInterface.Test;
begin
// do nothing
end;
procedure Execute (Proc : TProc);
begin
Proc;
end;
procedure MyListener (SomeInt : ISomeInterface);
begin
Execute (procedure
begin
SomeInt.Test;
end);
end;
var
Obj : ISomeInterface;
begin
try
ReportMemoryLeaksOnShutdown := True;
Obj := TSomeInterface.Create;
Obj.AddListener (MyListener);
Obj.NotifyListeners;
Obj := nil;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
Bạn nên cho chúng tôi biết cách hoạt động của AddListener. –
Tôi chỉ cần đặt chúng trong một 'TList. ' –
jpfollenius
Tất cả mã tôi nhìn thấy có vẻ tốt. Vấn đề phải nằm trong phần ẩn. Bạn có thể hiển thị một ví dụ hoàn chỉnh tạo ra sự rò rỉ không? –