type
TTest = class
a: integer;
end;
TTest2 = class(TTest)
b: integer;
end;
var c:TTest;
begin
c:=TTest2.Create();
c.Free;
end;
No, it will not.
A variable of a base class type can be used for instantiating objects from its child classes (they are type compatible), but take note that using such a variable, you will have access only to TTest members, not TTest2 members. That means; you can access "a", but not "b".
Also, if you face any exception during TTest2.Creation execution, Create won't return a partially built object.
However, if you have some other codes between TTest2.Create and c.Free calls, raising an exception in those codes can cause memory leak; because C.Free might not execute. In such a case you should use a try-finally block.
No, there is no memory leak here. The constructor only returns a new resource if it succeeds. You can only leak if the constructor succeeds and you fail to call Free. Since you do nothing in between the constructor and the call to Free, there can be no leak.
If a constructor fails then:
The destructor is called to free any resources.
An exception is raised.
The constructor does not return because the exception changes program flow.
The assignment to the object variable, c in your example, does not happen.
Note that the answer from #vcldeveloper which you have accepted is incorrect in stating that nil is returned. Nothing is returned from a constructor that raises.
You should always wrap Create/Free pairs with try/finally as follows:
obj := TMyClass.Create;
try
obj.DoSomething;
finally
obj.Free;
end;
You only need to protect the resource once it has been assigned. So you place the try after the assignment.
If you place the try before the constructor that is an error:
try
obj := TMyClass.Create;
obj.DoSomething;
finally
obj.Free;
end;
If the constructor fails then obj is not assigned and then when Free runs (and it will run thanks to the finally!) it is called on an uninitialized variable which results in undefined behaviour.
Related
In addition to this question I have made some tests and researches on the docwiki. My conclusion is that this kind of code should work without memory leaks:
function testResultObject: TClassA;
begin
Result := TClassA.Create;
Result.DoSomething;
end;
And then somewhere I can call the above code in this manner:
var k: TClassA;
begin
k := testResultObject;
try
//code code code
finally
k.Free;
end;
end;
As Remy suggested in the answer it's better to avoid this way of doing things and instead use something like testResultObject(x: TClassA): boolean. In this case the return true/false can tell me if everything went fine and I am passing an object already created.
Look at this code:
function testResultObject: TClassA;
begin
Result := TClassA.Create;
try
Result.DoSomething;
except
Result.Free;
end;
end;
The problem with the first version above of the function is that DoSomething could raise an exception and if so I'll leak memory. Can the second implementation with try-except be a solution? For sure later I'll have to check if the result is assigned or nil.
I agree that (as already said above) the testResultObject(x: TClassA): boolean would be better. I was just wondering if the return-a-class function way could be fixed as I've written.
Your code has serious problems. In case of an error, it swallows the exception, and returns an invalid object reference.
This is easy to fix. The canonical way is as follows:
function testResultObject: TClassA;
begin
Result := TClassA.Create;
try
Result.DoSomething;
except
Result.Free;
raise;
end;
end;
Either the function succeeds and returns a new object. Or it fails, cleans up after itself, and raises an exception.
In other words, this function looks and behaves just like a constructor. You consume it in the same way:
obj := testResultObject;
try
// do things with obj
finally
obj.Free;
end;
Your second approach works, but has 2 serious problems.
By swallowing all exceptions, (as J pointed out) you'll hide the fact that something went wrong.
There's no indication to the caller that you've created an object that the caller is responsible for destroying. This makes using the function more error prone; and easier to cause memory leaks.
I would recommend the following improvement on your second approach:
{Name has a clue that caller should take ownership of a new object returned}
function CreateObjectA: TClassA;
begin
{Once object is successfully created, internal resource protection is required:
- if no error, it is callers responsibility to destroy the returned object
- if error, caller must assume creation *failed* so must destroy object here
Also, by assigning Result of successful Create before *try*:
The object (reference) is returned
**if-and-only-if**
This function returns 'normally' (i.e. no exception state)}
Result := TClassA.Create;
try
Result.DoSomething; {that could fail}
except
{Cleanup only if something goes wrong:
caller should not be responsible for errors *within* this method}
Result.Free;
{Re-raise the exception to notify caller:
exception state means caller does not "receive" Result...
code jumps to next finally or except block}
raise;
end;
end;
The most important benefit of the above create function is that: as far as any caller/client code is concerned, it behaves exactly like a normal TObject.Create.
And so the correct usage pattern is exactly the same.
Note that I'm not keen on J's FreeAndNil suggestion because if calling code doesn't check if the result was assigned: it is likely to AV. And code that does check the result correctly will be a little messy:
var k: TClassA;
begin
k := testResultObject; {assuming nil result on failed create, next/similar is *required*}
if Assigned(k) then {Note how this differs from normal try finally pattern}
try
//code using k
finally
k.Free;
end;
end;
NB: It's important to note that you cannot ever have your caller simply ignore memory management; which brings me to the next section.
All the above aside, there is much less chance of making careless mistakes if your testResultObject takes an input object that you require the caller to create and manage its lifetime as needed. I'm not sure why you're resisting that approach so much? You cannot get simpler than the following without resorting to a different memory model.
var k: TClassA;
begin
k := TClassA.Create;
try
testResultObject(k); {Where this is simply implemented as k.DoSomething;}
//more code using k
finally
k.Free;
end;
end;
The only problem with this :
function testResultObject: TClassA;
begin
Result := TClassA.Create;
try
Result.DoSomething;
except
Result.Free;
end;
end;
Is that you have no way of knowing whether the function was successful. Freeing an object does not alter the reference; the variable will still point to the (now) invalid memory location where the object used to exist. You must explicitly set the reference to nil if you want the consumer to be able to test if the reference is valid. If you want to use this pattern (having the consumer test for nil) then you would need to do :
try
Result.DoSomething;
except
FreeAndNil(Result);
end;
This way the caller can test the result for nil (using Assigned or otherwise) as you intended. This still isn't a very clean approach, however, since you're still swallowing exceptions. Another solution might be to simply introduce a new constructor or alter the existing one. For example
TFoo = class
public
constructor Create(ADoSomething : boolean = false);
procedure DoSomething;
end;
constructor TClassA.Create(ADoSomething: Boolean = False);
begin
inherited Create;
if ADoSomething then DoSomething;
end;
procedure TClassA.DoSomething;
begin
//
end;
This way you can get rid of all of the exception handling and just call this as :
function testResultObject: TClassA;
begin
Result := TClassA.Create(true);
end;
Since you've now pushed the DoSomething execution into the constructor any exceptions will naturally automatically call the destructor and your memory management problems go away. The other answers also have good solutions.
SITUATION
I am going to write a class and the constructor is a custom one that I have made because I need to initialize some values. This is the code I've written so far:
type
TCombinatorio = class(TObject)
private
valN, valK: integer;
result: double;
public
property K: integer read valK;
property N: integer read valN;
constructor Create(valN: integer; valK: integer);
end;
constructor TCombinatorio.Create(valN: Integer; valK: Integer);
begin
inherited Create;
Self.valN := valN;
Self.valK := valK;
if ((valN < 0) or (valK < 0)) then
begin
raise Exception.Create('N and K must be >= 0');
end;
end;
Since I am going to do some math calculations, I need to avoid negative numbers.
QUESTION
Can I raise an exception in the constructor in that way? I am running the code in this way:
procedure TForm1.Button1Click(Sender: TObject);
var a: TCombinatorio;
b: string;
begin
a := TCombinatorio.Create(5,-2);
try
//some code
finally
a.Free;
end;
end;
As you can see here I have wrong parameters for my constructor, since the second is negative. I also cannot understand (according with the code of my constructor) if the a.Free inside the finally is really needed because when the constructor raises the exception, the destructor is called.
I thought to include the a := TCombinatorio.Create(5,-2); inside the try-finally block to avoid the problem but I am not sure. What do you think?
Your code is absolutely fine and correct. Raising exceptions from constructors is perfectly respectable. As you know the destructor is called.
You ask about this code:
a := TCombinatorio.Create(5,-2);
try
//some code
finally
a.Free;
end;
You are worried that Free will be called after the object has already been destroyed. That cannot happen. If an exception is raised in the constructor then it propagates up the call stack. That happens before the try block begins and so the finally block does not execute. Indeed the assignment to a does not happen.
Moving the creation inside the try would be disastrous and is in fact an incredibly common mistake. Suppose you did that:
// WARNING THIS CODE IS DEFECTIVE
try
a := TCombinatorio.Create(5,-2);
//some code
finally
a.Free;
end;
Now if an exception is raised then Free is called but on what? The variable a is not initialized. Even if it was, which it isn't, that would still be a double free.
OK, first you can raise an exception in the constructor, and yes it does call the destructor as a consequence. The code you show is fine. But I think you misunderstand what your code does. And to put the constructor inside a try finally block would be wrong. The point I think that you are missing is that if your constructor fails the try...finally block never gets executed and so the free is not executed. You should not call free if the constructor does not succeed, which is why you should not put the constructor inside the try...finally block.
First of all I would say that you cannot avoid exceptions in constructors so it cannot be an anti-pattern. If you check Delphi source code you will find number of places where exception is raised in constructor. For example
constructor TCustomForm.Create(AOwner: TComponent);
begin
// ... skipped some lines
if not InitInheritedComponent(Self, TForm) then
raise EResNotFound.CreateFmt(SResNotFound, [ClassName]);
The only thing you should know is that Delphi will automatically call the destructor if an exception escapes from the constructor. Actually it means that your destructor may be executed on a partially constructed object and it is your responsibility to write destructor properly. See TObject.Destroy documentation, and pay your special attention to the below quote:
Note: If an exception escapes from the constructor, the destructor is called to destroy the partially constructed object instance that
failed to initialize completely. Therefore, destructors should check
that allocated resources such as handles were actually allocated
before trying to release them, since their value might be zero.
PS In general you should assume that each line of code may raise an exception, but please do not be a paranoiac ;)
In that case I am usual add methods which check the data:
.. = class
function DataValid : boolean;
...
end;
Lots of benefit:
no exception in constructor. It simple copies its parameters to in-class fields.
special destructor for partially created class not needed.
simplicity of code.
I'm getting access violations from the unit DBXCommon.pas (in Delphi XE). When I look at the code I see things like the following (at the exclamation marks):
function TDBXConnectionFactory.GetConnection(const DBXContext: TDBXContext;
const ConnectionProperties: TDBXProperties): TDBXConnection;
var
ConnectionBuilder: TDBXConnectionBuilder;
DelegatePath: TDBXDelegateItem;
Connection: TDBXConnection;
CombinedProperties: TDBXProperties;
begin
//...
ConnectionBuilder := TDBXConnectionBuilder.Create;
Connection := nil;
try
//..lots of setting ConnectionBuilder properties
ConnectionBuilder.FInputPassword := CombinedProperties[TDBXPropertyNames.Password];
Connection := ConnectionBuilder.CreateConnection;
Connection.Open;
Result := Connection;
!! Connection := nil;
finally
!! Connection.Free;
ConnectionBuilder.Free;
end;
end;
But I see constructs like this (first assign Nil, then a Free) much more in DBXCommon.pas. Is this some construct I do not know, or is this really causing access violation every time this piece of code is called?
Calling Free on a null reference is always safe. Go look in the implementation of TObject.Free to see why.
This code is an example of a factory function. Its job is to create a new instance of a class, but if it fails, it needs to make sure it doesn't leak a half-created instance when it throws an exception, so it calls Free. When it's sure it's going to succeed, it transfers ownership of the result to the caller. It still calls Free, but if it's already transfered ownership, then it ends up calling Free on a null reference, and there's no harm done. This code is what transfers ownership:
Result := Connection;
Connection := nil;
The way I would write a factory function would do away with the separate Connection variable. I'd construct the result directly in Result, but free it if there were an exception, like this:
function TDBXConnectionFactory.GetConnection(const DBXContext: TDBXContext;
const ConnectionProperties: TDBXProperties): TDBXConnection;
var
ConnectionBuilder: TDBXConnectionBuilder;
DelegatePath: TDBXDelegateItem;
Connection: TDBXConnection;
CombinedProperties: TDBXProperties;
begin
//...
ConnectionBuilder := TDBXConnectionBuilder.Create;
try
//..lots of setting ConnectionBuilder properties
ConnectionBuilder.FInputPassword := CombinedProperties[TDBXPropertyNames.Password];
Result := ConnectionBuilder.CreateConnection;
try
Result.Open;
except
Result.Free;
raise;
end;
finally
ConnectionBuilder.Free;
end;
end;
That has the same effect.
It is safe to call Free on nil reference as it's implementation checks for Self <> nil before calling Destroy. See Allen Bauer's explanation in Embarcadero forum why TObject.Free was introduced. I include only the relevant quote here:
The sole reason for introducing the non-virtual Free method on TObject, was for use in destructors as a simple shorthand for:
if FField <> nil then
FField.Destroy;
TObject.Free is basically implemented as if Self <> nil then Destroy, so the code above should not raise any exception.
I have a method which constructs an object, calls an Execute method, and frees the object. The type of object is determined by a TClass descendant passed into the method.
Note this is Delphi for Win32 I am talking about, not .NET.
Edit: I should point out that this is Delphi 2006, as it has been noted in answers below that in future versions the NewInstance call may not be required. In my case, however, it is required. As such, I would imagine the answer to my question (is it safe? and does CreateForm() have a potential leak) would need to be answered on the basis that this is Delphi 2006
Edit#2: seems that the solutions given for D2007 & D2009 do in fact work for D2006. I must have picked up the "NewInstance" habit from an earlier version of Delphi...
function TPageClassFactory.TryExecute(ScrnClass: TCustomPageClass): boolean;
//TCustomPageClass = class of TCustomPage
var
ScrnObj: TCustomPage; //TCustomPage defines an abstract Execute() method
begin
Result := FALSE; //default
ScrnObj := TCustomPage(ScrnClass.NewInstance); //instantiate
try
ScrnObj.Create(Self); //NB: Create() and Execute() are *virtual* methods
ScrnObj.Execute;
finally
FreeAndNil(ScrnObj);
end;
Result := TRUE;
end;
What I want to know is whether this is safe - what will happen here if Create() raises an exception?
Looking at a similar example, from Forms.pas.TApplication.CreateForm(), a different approach has been taken to exception handling (I've cut out the irrelevant bits below):
procedure TApplication.CreateForm(InstanceClass: TComponentClass; var Reference);
var
Instance: TComponent;
begin
Instance := TComponent(InstanceClass.NewInstance);
TComponent(Reference) := Instance;
try
Instance.Create(Self);
except
TComponent(Reference) := nil;
raise;
end;
end;
In the Forms.pas method, does this mean that memory is leaked when an exception occurs in the Create() method? My understanding was that InstanceClass.NewInstance allocated memory, thus in this case the memory is not being deallocated/released/freed?
You should put the create out of the try finally block.
But a better solution is:
type
TMyClass = class ()
public
constructor Create(...); virtual;
function Execute: Boolean; virtual;
end;
TMyClassClass = class of TMyClass;
procedure CreateExecute(const AClass: TMyClassClass): Boolean;
var
theclass : TMyClass;
begin
theclass := AClass.Create;
try
Result := theclass.Execute;
finally
theclass.Free;
end;
end;
There have been a few questions raised in comments that I'd like to clarify.
First is the continued myth that the constructor needs to be virtual. It does not. Consider this example:
type
TBase = class
constructor Create(x: Integer);
end;
TDerived = class(TBase)
field: string;
end;
TMetaclass = class of TBase;
var
instance: TBase;
desiredClass: TMetaclass;
begin
desiredClass := TDerived;
instance := desiredClass.Create(23);
Assert(instance.ClassName = 'TDerived');
Assert(instance is TDerived);
Assert(instance.field = '');
end;
The created object will be a full-fledged instance of class TDerived. Enough memory will have been allocated to hold the string field, which didn't exist in the base class.
There are two conditions that must be true before you'll need a virtual constructor:
The constructor will be called virtually. That is, you'll have a variable of the base-class metaclass type, and it will hold a value of a derived class, and you will call a constructor on that variable. That's demonstrated in the code above. If all your constructor calls are directly on the class names themselves (i.e., TDerived.Create(23)), then there's nothing to be gained from virtual methods.
A subclass of the base class will need to override the constructor to provide class-specific initialization. If all descendants use the same construction, and only vary in other methods, ten there's no need to make the constructor virtual.
What's important to realize here is that those two rules are no different from the factors that determine when the make any other method virtual. Constructors aren't special in that regard.
The constructor knows which class to construct based not on the class where the constructor was defined, but on the class the constructor was called on, and that class is always passed as a hidden first parameter for every constructor call.
Second is the issue of whether NewInstance should be called in place of or in addition to the constructor. I think other comments have already established that it has nothing to do with compatibility with older Delphi versions. All versions have supported calling constructors on class references without the need for NewInstace. Rather, the confusion comes from looking at TApplication.CreateForm and treating it as an example of how things should be done. That's a mistake.
CreateForm calls NewInstance before calling the constructor because CreateForm's primary reason for existence is to ensure that the global form variable that the IDE declares is valid during the form's own event handlers, including OnCreate, which runs as part of the constructor. If the CreateForm method had done the usual construction pattern, then the global form variable would not yet have had a valid value. Here's what you might have expected to see:
TComponent(Reference) := InstanceClass.Create(Application);
Simple and obvious, but that won't work. Reference won't get assigned a value until after the constructor returns, which is long after the form has triggered some events. If you follow good programming practice and never refer to that variable from within the form class itself, then you'll never notice. But if you follow the documentation's instructions, which are written for an inexperienced audience, then you will refer to the global form variable from within the form's own methods, so the CreateForm method does what it can to make sure it's assigned in time.
To do that, it uses a two-step construction technique. First, allocate memory and assign the reference to the global variable:
Instance := TComponent(InstanceClass.NewInstance);
TComponent(Reference) := Instance;
Next, call the constructor on the instance, passing the TApplication object as the owner:
Instance.Create(Self);
It's my opinion that CreateForm should be called exactly once in any program. I'd prefer zero times, but it has the side effect of defining Application.MainForm, which is important for other aspects of a Delphi program.
Third is the notion that it's unusual for an object to call a constructor on itself.
In fact, this happens all the time. Every time you call an inherited constructor, you're calling a constructor on an object that already exists. The inherited constructor is not allocating a new object. Likewise, the VCL has some examples of non-inherited calls of constructors. TCustomForm.Create delegates much of its construction tasks to its CreateNew constructor.
Re your question about memory being leaked when Create() raises an exception: You should try it out for yourself. I just did on Delphi 2007, and with your code FastMM4 shows an error dialog about the attempt to call a virtual method on an already freed object, namely Destroy(). So the exception in Create will already lead to the destructor being called and the memory being freed, so your code is actually wrong. Stick to the idiom used in the answer by Gamecat, and everything should work.
Edit:
I just tried on Delphi 4, and the behaviour is the same. Test code:
type
TCrashComp = class(TComponent)
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;
constructor TCrashComp.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
raise Exception.Create('foo');
end;
destructor TCrashComp.Destroy;
begin
Beep;
inherited Destroy;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
C: TComponent;
begin
C := TComponent(TCrashComp.NewInstance);
try
C.Create(nil);
C.Tag := 42;
finally
C.Free;
end;
end;
With FastMM4 the Free in the finally block gives the same error, because C has been freed already. On application shutdown the exception and the exception string are reported as memory leaks, though. This is however not a problem with the code, but with the runtime.
Edit:
Didn't fully remember how it was in old delphi versions but apparently this should work in all based on other replies.
Note, Create has been calling Destroy on fail for as long as I can remember. It shouldn't be after I think.
Code would be:
procedure TPageClassFactory.TryExecute(ScrnClass: TCustomPageClass);
var
ScrnObj: TCustomPage;
begin
ScrnObj := ScrnClass.Create(Self); // Exception here calls the destructor
try
ScrnObj.Execute; // Exception here means you need to free manually
finally
FreeAndNil(ScrnObj); // Be free!
end;
end;
I removed the result returned by the original function as it can never be false, only "unassigned" (exception) or true. You could after all get an exception before you assign result to false. ;)
What is the best practice for returning simple objects from functions / procedures in delphi?
eg. 2 kinds of code:
pass created object as reference, populate object in Proc, destroy it afterwards
procedure Proc(var Obj: TMyObject);
begin
// populate Obj
end;
O := TMyObject.Create;
try
Proc(O);
// manipulate populated object
finally
O.Free;
end;
or
get created object as result from function, destroy after manipulation
function Func: TMyObj;
begin
Result := TMyObj.Create;
end;
O := Func;
if O <> nil then
begin
try
// manipulate
finally
O.Free;
end;
end;
There is no best practice. The primary thing you should do, though, is to make sure it's always clear who is responsible for destroying the object at any given time, even when an exception occurs.
There's nothing wrong with a function creating a new instance and returning it. Such a function is a factory. You can treat it just like a class's constructor, so you should make sure that it behaves like a constructor: Either return a valid object or throw an exception. It never returns a null reference.
function Func: TMyObj;
begin
Result := TMyObj.Create;
try
Result.X := Y;
except
Result.Free;
raise;
end;
end;
That's an exception-handling pattern you don't see very often, but it's important for this style of function. Returning the object transfers ownership from the function to the caller, but only if it manages to execute completely. If it has to leave early because of an exception, it frees the object because the caller has no way to free it itself. (Functions that terminate due to an exception do not have return values.) The caller will use it like this:
O := Func;
try
writeln(O.X);
finally
O.Free;
end;
If there's an exception in Func then O never gets assigned, so there's nothing available for the caller to free.
When the caller creates the object and you pass it to another function to initialize it, do not make the parameter a "var" parameter. That places certain restrictions on the caller, who must use a variable of exactly the type requested by the function, even if some descendant type was created instead.
Such a function should not free the object. The caller doesn't grant ownership responsibility to the functions it calls, especially when it plans on using the object after the function returns.
It depends on the lifetime of the object and on who is responsible for it.
Most of the time objects should be created and destroyed by the same entity.
Let's say your method fills a TStringList with results from parsing a file.
Should you let that function create the TStringList, or should you create it and pass as a reference?
I find it more readable to create it, pass it as reference, and later destroy, all in consecutive lines of code.
Now let's consider that you have a function that returns a TCustomer, for each customer added. In that case I would use a function, because I suppose that my entity would have a list, or something, of customers responsible for destroying them when not needed.
It is a common Delphi idiom to let the caller create the object and pass it as a parameter. Note that you don't have to declare it var in almost all cases.
procedure Proc (Obj : TMyObject)
begin
Obj.SomeProperty := 'SomeValue';
...
end;
Calling Code:
Obj := TMyObject.Create;
try
Proc (Obj);
finally
FreeAndNil (Obj);
end;
This avoids confusion about who has to free the object. Note that if you have a chain of method calls it can quicky become very complicated to keep track of objects that need to be freed somewhere along the line.
One more drawback: having creation and destruction scattered in the code makes it impossible to use try...finally blocks, which is just another helpful idiom to avoid resource leaks.
If you want your method to create the object, I would make it explicit in the function name, something like CreateAndInitializeList sounds right to me.
My rule is to have ownership and creation altogether. I always have the creator be the owner and thus have the responsability of destroying the object. The creation of the object is explicit in the invocation code, it is never a side effect of the invocation.
So the usual signatures of my functions are
function Func(o:tMyO): TMyO;
begin
// ....
Result := o;
end;
this way I may do either
o := func(TMyO.create);
or
o := TMyO.create;
// ...
func(o);
As mentioned, in general the same entity that created the object should free it and that means that the caller should create the object reference rather than having it done inside the function.
However, this is only possible if the caller knows the exact type of the item to be returned rather than a supertype. For instance:
var E: TEmployee;
E := CreateEmployee(EmployeeID); // Could return TEmployee or subclasses TManager or TRetiredEmployee
try
E.SendEmail(MessageText);
if (E is TRetiredEmployee) then
E.PrintLetter;
finally
E.Free;
end;
In cases like this, I find it's helpful to include the word "Create", or other indicator, in the name of the factory function I'm calling.
I often use the construct
FUNCTION SomeFunction(SL : TStrings = NIL) : TStrings;
BEGIN
IF Assigned(SL) THEN Result:=SL ELSE Result:=TStringList.Create;
// Use Result for the remainder of the function
END;
That way, I can use it both as a PROCEDURE with a passed-in reference, and as a FUNCTION which creates the instance itself.