I am using following class
mycalss = class
public
Self.timer1: TTimer;
Self.abitmap: tbitmap;
Self.animage: TImage;
Self.formxyz:form;
//some other declaration
//also having my own constructor and destructor overridden
end;
when a button is clicked myclass1 will be created and when other button is clicked myclass1 will be destroyed
begin
FreeAndNil(Self.timer1) ;
FreeAndNil(Self.abitmap) ;
FreeAndNil(Self.animage);
//others
Self.formxyz.Close ;
FreeAndNil(Self.formxyz);
FreeAndNil(Self) ;
inherited Destroy;
end;
when ever i click on create button the windows task manager is showing 800 kb increase in memory consumption and whenever i click destroy there is only 500kb decrease ,
I am quite sure that the size increment is taking place when it is creating(not because of other side effects)as my app is a simple one.
Question :Can I expect the delphi application to remove all the objects(~800kb) created to be removed on destroy operation(If i have done freeing properly)?.
First only free object that you allocated in the class - do not destroy the self variable
this will have some nice side effects when calling inherited and that inherited class also wants to free things.
The only reliable thing to check for memory leaks is to enable ReportMemoryLeaksOnShutdown or
even better - download the FastMM sources from sourceforge.
Second I think your encountering a speciality of the internal memory manager - the internal memory manager only frees memory of very large allocated blocks. Looking at the internals it reveals that the memory manager basically consists of 3 block managers, a small, a medium and
a manager for large blocks. For the small and medium blocks the manager keeps the memory and does not deallocate it to windows - the likelyhood that it will be reused in near future is quite high. It only immediately deallocates the memory for large blocks.
Your constructor and destructor should look like this:
constructor TMyClass.Create(AOwner: TComponent);
begin
inherited;
timer1:= TTimer.Create;
Bitmap1:= TBitmap.Create;
AnImage:= TImage.Create(AOwner);
...
end;
destructor TMyClass.Destroy;
begin
timer1.Free;
abitmap.Free;
animage.Free;
inherited Destroy;
end;
Because you are not reusing any members it makes no sense to call FreeAndNil.
Related
The problem I am facing is as follows.Please note I'm no pro at delphi pascal
To save a Large amount of memory and time I created a procedure:
procedure TForm1.Placeholder(tspath: STRING);
begin //rgbholder :TImage globally declared (Dinamicly create image)
rgbholder.Free;//Free previous image
rgbholder := timage.Create(self);
rgbholder.Width := 10;
rgbholder.Height := 10;
rgbholder.Visible := false;
rgbholder.Bitmap.LoadFromFile(TSpath);
end;
procedure TForm1.Image3Click(Sender: TObject);
begin
placeholder('Data\Grass\Grassanim1low.png');
bitmaplistanimation5.Stop;
bitmaplistanimation5.Loop := true;
//bitmaplistanimation5.AnimationBitmap.LoadFromFile('Data\Grass\Grassanim1low.png');
bitmaplistanimation5.AnimationBitmap.Assign( rgbholder.Bitmap);
bitmaplistanimation5.AnimationCount := 22;
bitmaplistanimation5.AnimationRowCount := 2;
bitmaplistanimation5.Duration := 2.5;
bitmaplistanimation5.PropertyName :='bitmap';
end;
Now my problem is freeing up that memory of the bitmaplistanimation5.AnimationBitmap.Assign(rgbholder.Bitmap);
When this code executes
bitmaplistanimation5.Stop;
bitmaplistanimation5.Enabled := false;
bitmaplistanimation5.AnimationBitmap.Free;
Everything goes well until I close the executable with a close; or by simply closing it with the exit in window.
After closing it throws a Application Error Exception EInvalidPointer in module Project1.exe at 00007A55. Invalid Pointer Operation
I don't think I'm trying to free memory that is already freed, I'm also not trying to free memory that was allocated somewhere other than the memory manager unless the placeholder procedure counts. Unless I'm missing something or not understanding something I should.
As a general rule, you should only call Free on an object that you created. You did not create this object, the TBitmapListAnimation control created it. So this code is a clear mistake on your part:
bitmaplistanimation5.AnimationBitmap.Free;
You will have to remove that.
I suspect that the right way to clear the memory from an FMX bitmap is to set the Width and Height properties of the bitmap to 0.
I wonder whether or not you really need to release this memory. If your program stops using the memory, and the system is short of memory, if can swap your unused memory to disk. It is common to find programmers who don't have a good understanding of virtual memory, taking actions like this that give no benefit. I would not be at all surprised if by trying to release this memory you actually made your program's performance worse rather than better.
SITUATION
I am studying Delphi from Marco Cantu's book and I already have experience with OOP because I usually work with Java and PHP. To better understand what I'm reading I've made this test:
type
TFraction = class
private
number: double;
num, den: integer;
fraction: string;
function hcf(x: integer; y: integer): integer;
public
constructor Create(numerator: integer; denominator: integer); overload;
constructor Create(value: string); overload;
function getFraction: string;
end;
This is a super easy class that converts a decimal number into a fraction. I'm not including the other parts of the code where I define constructors and functions since they aren't useful for my question. I am creating the object in this way.
var a: TFraction;
begin
a := TFraction.Create(225, 35);
ShowMessage(a.getFraction);
//The output of ^ is 45/7
a.Free;
end;
QUESTION
From what I've learnt, I know that I have to get rid of the object once I've used it and in fact I am using the Free. In this way I free the memory and I avoid memory leaks.
By the way I see that I also have the possibility to override a destructor. I don't understand very well the behavior of the Free and the Destroy. I use the Free when I have to get rid of an object that I don't need anymore. When I override a destructor I can free the object and also make other actions?
In short, when is it good to use the Free? And when should I prefer the Destroy?
In general, the destructor is used if you need to do something during object destruction which otherwise wouldn't be done automatically. Like freeing memory that you initialize in the constructor. In your example, there is no need to override the destructor, since (presumably) you don't create anything which needs to be destroyed manually.
Also, keep in mind that Destroy is not intended to be called by you at all - neither internally or externally. Free automatically takes care of calling that for you - with a little extra work going on. Free checks if the object is nil or not, and only calls Destroy if it's not nil.
Take this for example:
type
TMyObject = class(TObject)
private
FSomeOtherObject: TSomeOtherObject;
public
constructor Create;
destructor Destroy; override;
end;
constructor TMyObject.Create;
begin
inherited;
FSomeOtherObject:= TSomeOtherObject.Create;
end;
destructor TMyObject.Destroy;
begin
FSomeOtherObject.Free;
inherited;
end;
Just as an added note, the usage I see above is missing something. What if the code between Create and Free raises some exception? The procedure would exit, and it would never be free'd. So instead, you should use a try / finally block...
a := TFraction.Create(225, 35);
try
ShowMessage(a.getFraction);
finally
a.Free;
end;
This would ensure that no matter what happens between try and finally, the code between finally and end will always be called.
By the way I see that I also have the possibility to override a destructor. I don't understand very well the behavior of the Free and the Destroy.
Free() calls the destructor if the object pointer is not nil.
Destroy() is the actual destructor.
I use the Free when I have to get rid of an object that I don't need anymore. When I override a destructor I can free the object and also make other actions?
Yes. The destructor is called when the object is in the process of being destroyed. Overriding the destructor is a good place to perform cleanup actions related to the object that is being destroyed.
In short, when is it good to use the Free? And when should I prefer the Destroy?
You can call Destroy() directly, but it is generally preferred to call Free() instead and let it call Destroy() for you.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
TStringList of objects taking up tons of memory in Delphi XE
I have a program that takes a while to run and uses a fair amount of memory (starts out at about 800 mb, ends at about 1.1 GB).
The problem I'm having is that even though the amount of memory it's using is fine, the amount of memory commited goes over 4GB and gives me an "Out of Memory" error.
Here is a screen shot of Resource Monitor:
The main thing that takes up the memory is a TStringList filled with an object that has a bunch of different values and a few stringlists
Does anyone know why it is committing so much more memory than I need, and how can I make my program not do that?
The commit size is the amount of memory allocated by the program (but is not necessarily in physical memory). As mentioned in the comments, it is quite possible that the program has a memory leak (e.g., it creates objects possibly but does not delete them). So even if the amount of memory in use is "reasonable", it doesn't necessarily represent the amount actually allocated, and that amount in a 32-bit system can't "typically" exceed 4GB. This question discusses leak detection tools that might be useful.
Your software probably contains a memory leak. Put this little piece of code right after your program's "main" block (.dpr file - press F7 to get there).
{$WARN SYMBOL_PLATFORM OFF}
ReportMemoryLeaksOnShutdown := DebugHook <> 0;
So, the end result should look similar to this:
begin
{$WARN SYMBOL_PLATFORM OFF}
ReportMemoryLeaksOnShutdown := DebugHook <> 0;
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
Then, run your program until you get some big memory usage and simply quit it. Delphi will show a nice window giving you the size of the memory leak as well as some tips about where they might be happening.
Good luck!
You didn't showed code, but this effect appears to be the result of a memory leak.
So, this TStringList (I'll call it parent) have objects associated, which have its own child TStringLists (which I suppose have only strings).
The easier way to do this memory management is letting the TStringList do it for you:
If in the Delphi version you have TStringList has the OwnsObjects property, set it to true. With this, every call to Delete and Clear methods will call the destructor of the objects associated with the parent list - and this will work even if cll parent.Free. If it doesn't implement, you'll have to do it yourself - overriding the Delete, Clear and Destroy methods of TStringList in a descendant class.
Make sure the destructor of the child objects clean correctly the objects created inside it - if one of the stringlists in a child objects has owned objects, you could use the same strategy in the above item.
An (oversimplified) example:
TMyChildObject = class
private
fMyListOfMagazineNames,
// This one will have TBitmap instances associated with the dogs names
fMyListOfDogNamesAndPhotos : TStringList;
fName: String;
public
//[properties, methods, whatever]
property Name: string read fName write fName;
constructor Create; virtual;
destructor Destroy; override;
end;
constructor TMyChildObject.Create;
begin
inherited Create;
fMyListOfMagazineNames = TStringList.Create;
fMyListOfDogNamesAndPhotos = TStringList.Create;
fMyListOfDogNamesAndPhotos.OwnsObjects := True;
end;
destructor TMyChildObject.Destroy;
begin
fMyListOfMagazineNames.Free;
fMyListOfDogNamesAndPhotos.Free;
inherited Destroy;
end;
An example of use:
var
MyObjList: TStringList;
begin
MyObjList := TStringList.Create;
MyObjList.OwnsObjects := True;
// Create your child objects
// And Free them at once
MyObjList.Free;
end;
As was stated in your previous question - thanks for having selected one answer.
The main solution to your problem is not to allocate all objects in memory. If your 28 MB initial data consume more than 1 GB of memory, you have a lot of redundant information.
You shall modify your algorithm as such:
Use a SQL database instead to process your data without memory issue (with proper indexes) - may be SQLite3 or embedded Firebird will work very well;
Leave the data on the input files, the memory-map them instead of allocating a copy in memory: use getter methods for each properties, to retrieve the value on the fly;
Use a NoSQL database (like this) which may be faster than a SQL database for inserting rows, and consume less disk space and memory;
Or... consider compressing the objects content (a fast compression is a good option).
Normally using GDI+ in Delphi you can use a TPaintBox, and paint during the OnPaint event:
procedure TForm1.PaintBox1Paint(Sender: TObject);
var
g: TGPGraphics;
begin
g := TGPGraphics.Create(PaintBox1.Canvas.Handle);
try
g.DrawImage(FSomeImage, 0, 0);
finally
g.Free;
end;
end;
The problem with this paradigm is that creating a destroying a Graphics object each time is wasteful and poorly performing. Additionally, there are a few constructs availabe in GDI+ you can only use when you have a persistent Graphics object.
The problem, of course, is when can i create that Graphics object? i need to know when the handle becomes available, and then when it is no longer valid. i need this information so i can create and destroy my Graphics object.
Solution Attempt NÂș1
i can solve the creation problem by creating it when it is really needed - on the first time the paint cycle is called:
procedure TForm1.PaintBox1Paint(Sender: TObject);
begin
if FGraphics = nil then
FGraphics := TGPGraphics.Create(PaintBox1.Canvas.Handle);
FGraphics.DrawImage(FSomeImage, 0, 0);
end;
But i have to know when the device context is no longer valid, so i can destroy my FGraphcis object, so that it is re-created the next time it's needed. If for some reason the TPaintBox's device context gets recreated, i would be drawing on an invalid device context the next time OnPaint is called.
What is the intended mechanism in Delphi for me to know when the device context handle of a TPaintBox is created, destroyed, or re-created?
You can't with the standard TPaintBox because the TPaintBox has a Canvas of type TControlCanvas, for which members relevant to this issue are these:
TControlCanvas = class(TCanvas)
private
...
procedure SetControl(AControl: TControl);
protected
procedure CreateHandle; override;
public
procedure FreeHandle;
...
property Control: TControl read FControl write SetControl;
end;
The problem is that FreeHandle and SetControl are not virtual.
But: the TControlCanvas is created and assigned here:
constructor TGraphicControl.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FCanvas := TControlCanvas.Create;
TControlCanvas(FCanvas).Control := Self;
end;
So what you could do is create a descending TMyControlCanvas that does have virtual methods, and a TMyPaintBox that assigns the Canvas like this:
constructor TMyPaintBox.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FCanvas.Free;
FCanvas := TMyControlCanvas.Create;
TMyControlCanvas(FCanvas).Control := Self;
end;
Then you can use the methods in TMyControlCanvas to dynamically create and destroy your TGPGraphics.
That should get you going.
--jeroen
Detecting creation is easy. Just override CreateHandle in a descendant TControlCanvas and put yours in place of the default one as Jeroen's answer demonstrates. Detecting destruction is harder.
One way to avoid the issue is to check whether the TGpGraphics handle is equal to the paint-box's handle, so, rather than detect the moment when the device context is freed, you simply check before you need to know.
if not Assigned(FGraphics)
or (FGraphics.GetHDC <> PaintBox1.Canvas.Handle) then begin
FGraphics.Free;
FGraphics := TGpGraphics.Create(PaintBox1.Canvas.Handle);
end;
This probably isn't reliable, though; handle values are liable to be re-used, so although the HDC value might be the same between two checks, there's no guarantee that it still refers to the same OS device-context object.
The TCanvas base class never clears its own Handle property, so anything that invalidates the canvas must occur externally. TControlCanvas clears its Handle property when its Control property gets re-assigned, but that usually only happens when the control is created since TControlCanvas instances are rarely shared. However, TControlCanvas instances work from a pool of device-context handles kept in CanvasList. Whenever one of them needs a DC (in TControlCanvas.CreateHandle), it calls FreeDeviceContext to make room in the canvas cache for the handle it's about to create. That function calls the (non-virtual) FreeHandle method. The cache size is 4 (see CanvasListCacheSize), so if you have several descendants of TCustomControl or TGraphicControl in your program, chances are high that you'll get cache misses whenever more than four of them need to be repainted at once.
TControlCanvas.FreeHandle is not virtual, and it doesn't call any virtual methods. Although you could make a descendant of that class and give it virtual methods, the rest of the VCL is going to continue calling the non-virtual methods, oblivious to any of your additions.
Instead of trying to detect when a device context is released, you might be better off using a different TGpGraphics constructor. Use the one that takes a window handle instead of a DC handle, for instance. Window-handle destruction is much easier to detect. For a one-off solution, assign your own method to the TPaintBox.WindowProc property and watch for wm_Destroy messages. If you're doing this often, then make a descendant class and override DestroyWnd.
The performance hit you take for creating/destroying the graphics object is minimal. It's far outweighed by the performance hit of using gdi+'s drawing commands in the first place. Neither of which, imo, are worth worrying about when it comes to drawing user interfaces because the user wont notice anyways. And frankly, it can be very inconvenient to try to carry around a graphics object and track changes to the DC handle (especially if you're encapsulating graphics routines inside your own set of classes).
If you need to cache bitmaps, what you may consider doing is creating the bitmap you want to cache with GDI+ (make it the right size & w/ whatever antialias settings you want), saving it to a tmemorystream, and then when you need it, load it from a stream and draw it using good ol' bitblt. It'll be much, much faster than using Graphics.DrawImage. I'm talking orders of magnitude faster.
procedure TGraphicControl.WMPaint(var Message: TWMPaint);
begin
if Message.DC <> 0 then
begin
Canvas.Lock;
try
Canvas.Handle := Message.DC;
try
Paint;
finally
Canvas.Handle := 0;
end;
finally
Canvas.Unlock;
end;
end;
end;
Canvas.Handle := Message.DC;
Suppose my Delphi classes look like this:
interface
type
TMySubInfo = class
public
Name : string;
Date : TDateTime;
Age : Integer;
end;
TMyInfo = class
public
Name : string;
SubInfo : array of TMySubInfo;
destructor Destroy; override;
end;
implementation
destructor TMyInfo.Destroy;
begin
// hmmm..
end;
end.
To properly clean up, what should go in the destructor? Is it enough to do SetLength(SubInfo,0), or do I need to loop through and free each TMySubInfo? Do I need to do anything at all?
You need to loop through and free each created object.
You must know, that declaring a array of TMySubInfo doesn't actually create the objects. You have to create them later on.
I would use a TList instead for a more dynamic approach. You could even use a TObjectList that can free all its items when the list gets freed.
You should free each item, like this
destructor TMyInfo.Destroy;
var
I: Integer;
begin
for I:= Low(SubInfo) to High(SubInfo) do
SubInfo[I].Free;
SetLength(SubInfo, 0);
inherited;
end;
You free the objects the same way you allocated them. If you assigned an element's value by calling the constructor of a class, then free the object referenced by that element.
destructor TMyInfo.Destroy;
var
info: TMySubInfo;
begin
for info in SubInfo do
info.Free;
inherited;
end;
That uses syntax introduced in Delphi 2005. If you have an older version, use an explicit loop-control variable:
var
i: Integer;
begin
for i := 0 to High(SubInfo) do
SubInfo[i].Free;
You don't need to call SetLength at the end. A dynamic-array field like SubInfo gets released automatically when the object is destroyed. It works the same as interface, string, and Variant fields.
Agreed with all the above suggestions, but I want to add an (admittedly somewhat anal) recommendation that you always call the FreeAndNil() procedure in preference to the Free method.
Sooner or later you will accidentally access an object that you have already freed. If you have the habit of FreeAndNil-ing everything, then you get an immediate a/v on the line that contains the problem. If you merely Free'd the object, you will likely get a mysterious and apparently unconnected failure some time later...
This might seem obsessive in the context of a destructor, as here. Ok, it is a bit, but either one does it everywhere or not at all.
It is also anal, but Like to free in the reverse order to the creation, for example:
For I := List.Count-1 downto 0 do
List[I].Free;
I view creation and destruction as parethesis () although it makes litte actual execution diference.
Bri
If you created the objects via constructor calls, you need to make calls to Free to free them. If not, you don't.
For every new there should be a free.
Can you not use Finalize?