Tôi muốn tạo một lớp TParent
chứa một số đối tượng con bằng cách sử dụng tập hợp. Một số đối tượng là độc lập, trong khi một số có thể cũng phụ thuộc vào các trẻ khác. Tất cả các đối tượng trẻ em phải có một tham chiếu đến phụ huynh. Tôi cũng muốn sử dụng các giao diện nếu có thể.Delphi: Kết hợp đối tượng và rò rỉ bộ nhớ bằng thuộc tính [yếu]
Vì mục đích này, tôi đang sử dụng TInterfacedObject
cho TParent
và TAggregatedObject
cho trẻ em. Vì cả hai đứa trẻ và cha mẹ đều biết về nhau, tôi sử dụng các tham chiếu yếu để tránh sự phụ thuộc vào circuar. Thực tế, hành vi này đã được xác định trong TAggregatedObject
. Mọi thứ hoạt động tốt khi tôi chỉ sử dụng các đối tượng con độc lập (TIndependantChild
).
Sự cố phát sinh khi đối tượng con cũng phụ thuộc vào các trẻ khác, xem hàm tạo của TDependantChild
. Tôi lưu trữ các tham chiếu đến một đối tượng con khác trong biến fChild, được đánh dấu bằng attibute [weak]
, được giới thiệu trong Delphi 10 Berlin. FastMM4 báo cáo rò rỉ bộ nhớ trên shutdown:
Ngoài truy cập vi phạm dẫn đến System.TMonitor.Destroy
tăng lương, nhưng điều này chỉ xảy ra khi FastMM4 là trong việc sử dụng và ReportMemoryLeaksOnShutDown là True.
program Project1;
{$APPTYPE CONSOLE}
uses
FastMM4,
System.SysUtils;
type
IParent = interface
['{B11AF925-C62A-4998-855B-268937EF30FB}']
end;
IChild = interface
['{15C19A4E-3FF2-4639-8957-F28F0F44F8B4}']
end;
TIndependantChild = class(TAggregatedObject, IChild)
end;
TDependantChild = class(TAggregatedObject, IChild)
private
[weak] fChild: IChild;
public
constructor Create(const Controller: IInterface; const AChild: IChild); reintroduce;
end;
TParent = class(TInterfacedObject, IParent)
private
fIndependantChild: TIndependantChild;
fDependantChild: TDependantChild;
public
constructor Create;
destructor Destroy; override;
end;
{ TParent }
constructor TParent.Create;
begin
fIndependantChild := TIndependantChild.Create(Self);
fDependantChild := TDependantChild.Create(Self, fIndependantChild);
end;
destructor TParent.Destroy;
begin
fDependantChild.Free;
fIndependantChild.Free;
inherited;
end;
{ TDependantChild }
constructor TDependantChild.Create(const Controller: IInterface; const AChild: IChild);
begin
inherited Create(Controller);
fChild := AChild;
end;
var
Owner: IParent;
begin
ReportMemoryLeaksOnShutDown := True;
Owner := TParent.Create;
Owner := nil;
end.
tôi thấy, rằng việc sử dụng [an toàn] thay vì [yếu] giải quyết vấn đề, nhưng theo delphi help
Nó ([an toàn]) nên chỉ được sử dụng bên ngoài đơn vị hệ thống trong những tình huống rất hiếm.
Vì vậy, tôi không tin, tôi nên sử dụng [unsafe]
tại đây, đặc biệt là khi tôi không hiểu điều gì xảy ra.
Vì vậy, những gì là những người trấn an các rò rỉ bộ nhớ trong tình huống này và cách khắc phục chúng?
Tại sao trẻ cần được tổng hợp? Bạn có hiểu tổng hợp thực sự là gì không? Tại sao bạn trộn các tham chiếu và giao diện đối tượng? Đó luôn là một công thức cho thảm họa. Sử dụng trình gỡ lỗi để xem lý do bạn đang rò rỉ bộ nhớ. –
'[weak]' được thêm vào cho giao diện ở 10.1 Berlin, nhưng '[weak]' tồn tại trong các phiên bản trước đó. Tôi có thể biên dịch mã của bạn như là trong XE2, nhưng '[yếu]' không có hiệu lực. 'Chủ sở hữu' có' RefCount = 1' vì 'TDependantChild' có tham chiếu không yếu tới' TParent' (do tập hợp) khi 'fChild' được gán, mặc dù là' [yếu] '. Khi 'Owner' bị hủy,' TInterfacedObject.BeforeDestruction() 'gây ra lỗi khi' RefCount <> 0', khiến 'Owner' và con của nó bị rò rỉ. Thay đổi 'fChild' thành' Pointer' sẽ sửa lỗi đó. Tôi nghi ngờ một cái gì đó tương tự trong trường hợp của bạn khi sử dụng '[không an toàn]'. Xác nhận với trình gỡ lỗi –
Remy, Cảm ơn bạn đã nhận xét. Tôi mới đến khái niệm tập hợp, có thể là, tôi hiểu nó sai. Trong trường hợp của tôi, các đối tượng con đại diện cho một số chức năng lớp nhất định. Họ không có sence mà không có cha mẹ, nhưng các đối tượng con tương tự có thể được sử dụng để soạn bố mẹ khác nhau. Tôi không thích trộn giao diện và tham chiếu đối tượng quá, nhưng tôi tìm thấy một số ví dụ nơi nó đã được thực hiện để [link] (https://stackoverflow.com/questions/3483680/delphi-how-delegate-interface-implementation-to-child -object), và nó đưa ra lỗi khi chỉ sử dụng giao diện. Tôi sẽ kiểm tra lại lần thứ hai. – VyPu