elGringo Posted October 26, 2018 Posted October 26, 2018 look at this class unit uGC; interface uses System.Generics.Collections, Rtti, System.Classes; type TGarbageCollector = class(TComponent) public const DEFAULT_TAG = 'DEFAULT_TAG'; private items: TDictionary<TObject, string>; public destructor Destroy; override; constructor Create(AOwner: TComponent); override; function Add<T>(item: T): T; overload; function Add<T>(item: T; const tag: string): T; overload; procedure Collect(const tag: string); end; var GC: TGarbageCollector; implementation uses System.Types, System.SysUtils; constructor TGarbageCollector.Create(AOwner: TComponent); begin inherited; items := TObjectDictionary<TObject, string>.Create([doOwnsKeys]); end; destructor TGarbageCollector.Destroy; begin items.free(); inherited Destroy; end; function TGarbageCollector.Add<T>(item: T): T; begin result := Add(item, DEFAULT_TAG); end; function TGarbageCollector.Add<T>(item: T; const tag: string): T; var obj: TObject; v: TValue; begin v := TValue.From<T>(item); if v.IsObject then begin items.add(v.AsObject, tag); result := item; end else raise Exception.Create('not an Object'); end; procedure TGarbageCollector.Collect(const tag: string); var key: TObject; item: TPair<TObject, string>; gcList: TList<TObject>; begin gcList := TList<TObject>.Create(); try for item in items do begin if (item.Value = tag) then gcList.add(item.Key); end; for key in gcList do items.remove(key); finally gcList.free(); end; end; end. Create it program GarbageCollector; uses Vcl.Forms, uMain in 'uMain.pas' {Main}, uGC in 'uGC.pas', uSomeClass in 'uSomeClass.pas'; {$R *.res} begin Application.Initialize; Application.MainFormOnTaskbar := True; GC := TGarbageCollector.Create(Application); // <<< Application.CreateForm(TMain, Main); Application.Run; end. use it someInstance := GC.Add(TSomeClass.Create(nil), 'TSomeClassTag'); // do smth with someInstance //now destroy GC.Collect('TSomeClassTag'); // anotherInstance := GC.Add(TSomeClass.Create(nil), 'TSomeClassTag'); // do smth with anotherInstance // not destroying here - will be destroyed on app destroy... what do you think? Quote
jaromir Posted October 29, 2018 Posted October 29, 2018 Hi. For me it is not good idea. What do You want to achive ? Cleaning memory after application close ? For me leak is mistake / error and I want to repair all this mistakes. I use fastmm or similar solution with full debug mode. All leaks should be repaired at place where they appear. Cleaning all leaks at app close is dirty solution. Your app can work long time without restart and it should consume as small amount of memory as possible. Quote
elGringo Posted October 30, 2018 Author Posted October 30, 2018 hm... agree with you, just it was start for discussion about the memory management in Delphi. So, could you say how do you look for memory leaks with fastMM - i don't know that for the moment. I use only ReportMemoryLeaksOnShutdown := true; But this approach only says me that there is a memory leak and what is leaking TStringList or etc... But how, for example you find memory leak in special exact place of code? Regards, Stan Quote
elGringo Posted October 30, 2018 Author Posted October 30, 2018 Another alternative to the class i showed is ARC, but here we should know about weak, unsafe links and raw pointers I'm reading now book Delphi Memory Management for Classic and ARC Compilers... Quote
elGringo Posted October 30, 2018 Author Posted October 30, 2018 and besides, my topic start code here gives 2 possibilities -manage code manually as usual, by grouping instances by tag -100 % clear on App Close if you have forgotten to clear smth inside the scope (protection from human factor...) Regards... Quote
elGringo Posted October 30, 2018 Author Posted October 30, 2018 And what about this example? Wrapper for classes, based on ARC ? Looks smart ))) So, you may avoid try... finally... and just Create Use Forget ))) unit uSmartPointer; interface type ISmartPointer<T> = reference to function: T; TSmartPointer<T: class, constructor> = class(TInterfacedObject, ISmartPointer<T>) private FValue: T; function Invoke: T; procedure SetValue(const Value: T); public constructor Create; overload; constructor Create(AValue: T); overload; destructor Destroy; override; function Extract: T; property Value: T read FValue write SetValue; end; implementation constructor TSmartPointer<T>.Create; begin inherited Create; FValue := T.Create; end; constructor TSmartPointer<T>.Create(AValue: T); begin inherited Create; FValue := AValue; end; destructor TSmartPointer<T>.Destroy; begin FValue.Free; inherited; end; function TSmartPointer<T>.Invoke: T; begin Result := FValue; end; procedure TSmartPointer<T>.SetValue(const Value: T); begin FValue := Value; end; function TSmartPointer<T>.Extract: T; begin Result := FValue; FValue := nil; end; end. Example of use procedure Smart; var sl: ISmartPointer<TStringList>; begin sl := TSmartPointer<TStringList>.Create(); sl.Add('I am inside automanaged StringList'); end; Quote
Abaksoft Posted October 30, 2018 Posted October 30, 2018 El Gringo, Thx to share your experience and BRAVO for your learning ! About memory leaks, if you know your code and what are you doing, ReportMemoryLeaksOnShutdown := true; is enough. You will find easily your leaks. Quote
elGringo Posted October 30, 2018 Author Posted October 30, 2018 Thnks! Just thought there is the way that shows "SomeUnit, string 157, memoryLeak 120 Kb, TStringList" )) Quote
jaromir Posted October 31, 2018 Posted October 31, 2018 On 10/30/2018 at 5:50 AM, elGringo said: But how, for example you find memory leak in special exact place of code? Regards, Stan Hello Stan I’m not at screen at this moment so I give You only brief. First You have to enable FullDebugMode in FastMM configuration file. You have to remove dot at proper line. Next You have to enable „include debug info” at compilator options. After next build You can execute app. During app close, if any leak will be detected You will see detailed log file with code lines whitch makes leaks. Don’t forget to disable including debug info in next builds because it makes exe much more bigger in size. Best regards Jaromir Quote
jaromir Posted October 31, 2018 Posted October 31, 2018 One more thing. You have to place dll from FastMM bin next to Your exe. It is something like FullDebug...dll. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.