Why does FreeAndNil sets nil before freeing the object? [duplicate] - delphi

If you will look at the code of FreeAndNil procedure you will see:
procedure FreeAndNil(var Obj);
var
Temp: TObject;
begin
Temp := TObject(Obj);
Pointer(Obj) := nil;
Temp.Free;
end;
What is the reason they assigning Nil to an object reference and only after this destroying it? Why not vice-versa?

I can think of two reasons for doing it this way round, neither of which seems at all compelling.
Reason 1: to guarantee that the reference is set to nil in case an exception is raised
The implementation achieves this. If the destructor raises, then the reference is still set to nil. Another way to do so would be with a finally block:
try
TObject(Obj).Free;
finally
TObject(Obj) := nil;
end;
The downside of this is performance. Particularly on x86 a try/finally is a little expensive. In such a fundamental routine it is prudent to avoid this expense.
Why do I find the desire to nil at all costs not to be compelling? Well, as soon as destructor start failing you may as well give up. You can no longer reason clearly about your program's state. You cannot tell what failed and what state your program is in. It is my view that the correct course of action in the face of a destructor that raises is to terminate the process.
Reason 2: to ensure that other threads can detect that the object is being destroyed
Again this is achieved but it is of no practical use. Yes you can test whether the reference is assigned or not. But then what? The other thread cannot call methods on the object without synchronization. All you could do is learn whether or not the object is alive. And if that is so, why would it matter if this status changed before or after the destructor runs?
So whilst I present this as a possible reason I cannot believe that anyone in Embarcadero was really swayed by this argument.

There's a variation on David's second reason that is a little more compelling. Although one might argue that if it applies there are other problems that should be fixed.
Reason 3: to ensure event handlers on the same thread can detect that the object is being destroyed
Here's a concocted hypothetical example:
TOwner.HandleCallback;
begin
if Assigned(FChild) then
FChild.DoSomething;
end;
TChildClass.Destroy;
begin
if Assigned(FOnCallback) then FOnCallback;
inherited Destroy;
end;
Now if TOwner calls:
FChild.Free;
FChild := nil;
FChild will be asked to DoSomething in the middle of its destruction cycle. A certain recipe for disaster. The implementation of FreeAndNil neatly avoids this.
Yes you may argue that firing callback events during destruction is dangerous, but it does have its benefits. There are quite few examples in Delphi/VCL code. Especially if you expand the scope of concern to include calling polymorphic methods - which also put aspects of the destruction sequence outside of your control.
Now I must point out that I'm not aware of any specifc cases in Delphi library code where this problem could manifest. But there are some complex circular dependencies in parts of the VCL. So I wouldn't be surprised if changing the implementation to the more obvious choice in SysUtils leads to a few unpleasant surprises.

The only thing that really bothered me for years is that FreeAndNil(var obj) lacks type safety. I know that due to the lack of adequate language support there was simply no way to do it right, but since we have generics for a while, here's a quick and simple tool that can make your life easier.
type
TypeSafe = class sealed
public
class procedure FreeAndNil<T : class>( var obj : T); static; inline;
end;
class procedure TypeSafe.FreeAndNil<T>( var obj : T);
begin
SysUtils.FreeAndNil( obj);
end;
If you add an overload for the normal FreeAndNil(var Obj) and mark it as deprecatedyou got a fair chance to find all the places where someone hands over an interface pointer to it -- and if the code base is only large enough you will find interesting things, believe me.
procedure FreeAndNil(var Obj); inline; deprecated 'use TypeSafe.FreeAndNil<T>() instead';
Note that you don't even have to specify the <T>since the compiler is smart enough to find out the right type for you. Just add the unit on top and change all
FreeAndNil(foobar);
in your source code into
TypeSafe.FreeAndNil(foobar);
and you're done.

Related

Delphi Custom Component Knowing Which Referee Called A Method

I have created a custom component which has a property that the user can assign to another custom component..
TComp1 = class(TComponent)
public
property Comp2: TComp2 read GetComp2 write SetComp2;
property Something;
end;
TComp2 = class(TComponent)
public
procedure DoSomething;
end;
There could be multiple TComp1 components that assign the same TComp2. I need TComp2 to know which TComp1 called it because it needs to reference property "something" of that specific referee..
var
comp1a, comp1b: TComp1;
comp2: TComp2;
comp2 := TComp2.create;
comp1a := TComp1.create;
comp1b := TComp1.create;
comp1a.comp2 := comp2;
comp1b.comp2 := comp2;
comp1b.comp2.dosomething; <-- needs to know this was from comp1b not comp1a
obviously, the code above is just to illustrate my point and is not including the notification mechanisms that I have to put in place, etc.
so far, I have considered using the getter for TComp1.Comp2 to set an "activeComponent" property on the assigned TComp2 so that TComp2 can use that property to get the right component. While this should work, I believe it is unsafe and if someone tries to use comp2 directly or passes the reference to another variable entirely (comp := comp1a.comp2; comp.dosomething;), or tries to use it from multiple threads, there could be issues.
has anybody else encountered this issue? what is the best solution?
I hope somebody will be able to help :)
In the line:
comp1b.comp2.dosomething; <-- needs to know this was from comp1b not comp1a
The call to doSomething has absolutely no knowledge of comp1b. You should think of this as two separate lines of code:
LocalComp2 := comp1b.comp2;
LocalComp2.doSomething;
So as per David's comment, you need to pass the other component as a parameter. I.e.
comp1b.comp2.doSomething(comp1b);
This, by the way, is a stock-standard technique used throughout Delphi code. The best example is TNotifyEvent = procedure (Sender: TObject) of object; and is used in calls like:
ButtonClick(Self);
MenuItemClick(MainMenu);
You ask in a comment:
I have thought about that too but it seems somewhat redundant to effectively reference the same component twice.. comp1a.comp2.domsomething(comp1a); is there no better way?
As I said, the bit comp2.domsomething has no knowledge of the comp1a. just before it. So as far as the compiler is concerned it's not redundant. In fact it's also possible to call comp1a.comp2.domsomething(SomeOtherComponent).
However, that said, there is a better way.
Currently your code violates a princple called the Law of Demeter. Users of TComp1 are exposed to details abobut TComp2 even if they don't care about TComp2. This means that you can find yourself repeatedly writing:
comp1a.comp2.doSomething(comp1a);
comp1b.comp2.doSomething(comp1b);
comp1a.comp2.doSomething(comp1a);
comp1c.comp2.doSomething(comp1c);
To avoid that, fix the Law of Demeter violation by writing:
procedure TComp1.doSomething;
begin
comp2.doSomething(Self);
end;
Now your earlier lines become:
comp1a.doSomething;
comp1b.doSomething;
comp1a.doSomething;
comp1c.doSomething;
The obvious solution is to pass the extra information as a parameter. Like this:
comp1b.comp2.dosomething(comp1b);
Expecting comp2 to be able to work out whether it was referenced from comp1a or comp1b is unrealistic, and frankly would be an indication of a poor design.
Parameters are explicit and so demonstrate clear intent to the reader.

Why FreeAndNil implementation doing Nil before Free?

If you will look at the code of FreeAndNil procedure you will see:
procedure FreeAndNil(var Obj);
var
Temp: TObject;
begin
Temp := TObject(Obj);
Pointer(Obj) := nil;
Temp.Free;
end;
What is the reason they assigning Nil to an object reference and only after this destroying it? Why not vice-versa?
I can think of two reasons for doing it this way round, neither of which seems at all compelling.
Reason 1: to guarantee that the reference is set to nil in case an exception is raised
The implementation achieves this. If the destructor raises, then the reference is still set to nil. Another way to do so would be with a finally block:
try
TObject(Obj).Free;
finally
TObject(Obj) := nil;
end;
The downside of this is performance. Particularly on x86 a try/finally is a little expensive. In such a fundamental routine it is prudent to avoid this expense.
Why do I find the desire to nil at all costs not to be compelling? Well, as soon as destructor start failing you may as well give up. You can no longer reason clearly about your program's state. You cannot tell what failed and what state your program is in. It is my view that the correct course of action in the face of a destructor that raises is to terminate the process.
Reason 2: to ensure that other threads can detect that the object is being destroyed
Again this is achieved but it is of no practical use. Yes you can test whether the reference is assigned or not. But then what? The other thread cannot call methods on the object without synchronization. All you could do is learn whether or not the object is alive. And if that is so, why would it matter if this status changed before or after the destructor runs?
So whilst I present this as a possible reason I cannot believe that anyone in Embarcadero was really swayed by this argument.
There's a variation on David's second reason that is a little more compelling. Although one might argue that if it applies there are other problems that should be fixed.
Reason 3: to ensure event handlers on the same thread can detect that the object is being destroyed
Here's a concocted hypothetical example:
TOwner.HandleCallback;
begin
if Assigned(FChild) then
FChild.DoSomething;
end;
TChildClass.Destroy;
begin
if Assigned(FOnCallback) then FOnCallback;
inherited Destroy;
end;
Now if TOwner calls:
FChild.Free;
FChild := nil;
FChild will be asked to DoSomething in the middle of its destruction cycle. A certain recipe for disaster. The implementation of FreeAndNil neatly avoids this.
Yes you may argue that firing callback events during destruction is dangerous, but it does have its benefits. There are quite few examples in Delphi/VCL code. Especially if you expand the scope of concern to include calling polymorphic methods - which also put aspects of the destruction sequence outside of your control.
Now I must point out that I'm not aware of any specifc cases in Delphi library code where this problem could manifest. But there are some complex circular dependencies in parts of the VCL. So I wouldn't be surprised if changing the implementation to the more obvious choice in SysUtils leads to a few unpleasant surprises.
The only thing that really bothered me for years is that FreeAndNil(var obj) lacks type safety. I know that due to the lack of adequate language support there was simply no way to do it right, but since we have generics for a while, here's a quick and simple tool that can make your life easier.
type
TypeSafe = class sealed
public
class procedure FreeAndNil<T : class>( var obj : T); static; inline;
end;
class procedure TypeSafe.FreeAndNil<T>( var obj : T);
begin
SysUtils.FreeAndNil( obj);
end;
If you add an overload for the normal FreeAndNil(var Obj) and mark it as deprecatedyou got a fair chance to find all the places where someone hands over an interface pointer to it -- and if the code base is only large enough you will find interesting things, believe me.
procedure FreeAndNil(var Obj); inline; deprecated 'use TypeSafe.FreeAndNil<T>() instead';
Note that you don't even have to specify the <T>since the compiler is smart enough to find out the right type for you. Just add the unit on top and change all
FreeAndNil(foobar);
in your source code into
TypeSafe.FreeAndNil(foobar);
and you're done.

Access Violation when handling forms

I have procedure to show/hide one element on TForm like that:
procedure ShowHideControl(const ParentForm: TForm; const ControlName: String; ShowControl: Boolean);
var
i: Integer;
begin
for i := 0 to pred(ParentForm.ComponentCount) do
begin
if (ParentForm.Components[i].Name = ControlName) then
begin
if ShowControl then
TControl(ParentForm.Components[i]).Show
else
TControl(ParentForm.Components[i]).Hide;
Break;
end;
end;
end;
then I try to use it like:
procedure TForm1.Button6Click(Sender: TObject);
begin
ShowHideEveryControl(TForm(TForm1), 'Button4', True);
end;
Why do I get Access Violation on Button6 click?
For me everything is OK... Button4 exists as a child :)
This cast is wrong:
TForm(TForm1)
You are telling the compiler to ignore the fact that TForm1 is not a TForm instance, and asking it to pretend that it is. That is fine until you actually try to use it as an instance, and then the error occurs.
You need to pass a real instance to a TForm descendent. You can write it like this:
ShowHideEveryThing(Self, 'Button4', True);
Just in case you are not clear on this, the parameter of your procedure is of type TForm. That means you need to supply an instance of a class that either is, or derives from TForm. I repeat, you must supply an instance. But you supply TForm1 which is a class.
And then the next problem comes here:
if (ParentForm.Components[i].Name = FormName) then
begin
if ShowForm then
TForm(ParentForm.Components[i]).Show
else
TForm(ParentForm.Components[i]).Hide;
Break;
end;
Again you have used an erroneous cast. When the compiler tells you that it a particular object does not have a method, you must listen to it. It's no good telling the compiler to shut up and pretend that an object of one type is really an object of a different type. Your button is categorically not a form, so don't try to cast it to TForm.
It is very hard to know what you are actually trying to do here. When you write:
ShowHideEveryThing(Self, 'Button4', True);
It would seem to me to me more sensible to write:
Button4.Show;
It is not a good idea to refer to controls using their names represented as text. It is much safer and cleaner to refer to them using reference variables. That way you let the compiler do its job and check the type safety of your program.
The names used in your function are suspect:
procedure ShowHideEveryThing(const ParentForm: TForm; const FormName: String;
ShowForm: Boolean);
Let's look at them:
ShowHideEveryThing: but you claim that the function should show/hide one element. That does not tally with the use of everything.
FormName: you actually pass a component name, and then look for components owned by ParentForm that have that name. It seems that FormName is wrong.
ShowForm: again, do you want to control visibility of the form, or a single element?
Clearly you need to step back and be clear on the intent of this function.
As an aside, you should generally never need to write:
if b then
Control.Show
else
Control.Hide;
Instead you can write:
Control.Visible := b;
My number one piece of advice to you though is to stop casting until you understand it properly. Once you understand it properly, design your code if at all possible so that you don't need to cast. If you ever really do need to cast, make sure that your cast is valid, ideally by using a checked cast with the as operator. Or at least testing first with the is operator.
Your code shows all the hallmarks of a classic mistake. The compiler objects to the code that you write. You have learnt from somewhere that casting can be used to suppress these compiler errors and now you apply this technique widely as a means to make your program compile. The problem is that the compiler invariably knows what it is talking about. When it objects, listen to it. If ever you find yourself suppressing a compiler error with a cast, take a step back and think carefully about what you are doing. The compiler is your friend.

Why Delphi compiler can't see I'm trying to free an interface?

I've done a small mistake while coding this week-end.
In the following code, I'm creating an object and cast it to an interface. Later, I'm trying to free it with FreeAndNil();
type
IMyIntf = interface
[...]
end;
TMyClass = class(TInterfacedObject, IMyIntf)
[...]
end;
var
Myintf : IMyIntf;
begin
Myintf := TMyClass.Create;
[...] // Some process
FreeAndNil(Myintf); // CRASH !!!
end;
Of course, the program crash at this line.
I totally understand the issue, but what I don't understand is why the compiler doesn't warn me about it ? There is no dynamic things behind, it's just that I'm trying to free an interface !!! Why don't it write me an error / warning ?
Is there any real explanation behind or is it just a compiler limitation ?
As you know, the correct way to do this is to write Myintf := nil, or just to let it go out of scope. The question you ask is why the compiler accepts FreeAndNil(Myintf) and does not complain at compile time.
The declaration of FreeAndNil is
procedure FreeAndNil(var Obj);
This is an untyped parameter. Consequently it will accept anything. You passed an interface, but you could have passed an integer, a string and so on.
Why did the designers choose an untyped parameter? Well, they needed to use a var parameter since the whole purpose of FreeAndNil is to free the object and set the object reference to nil. That can't be done by a method of the target object and so a var parameter of a standalone function is needed.
You might imagine that you could write
procedure FreeAndNil(var Obj: TObject);
since all objects are descended from TObject. But this does not do the job. The reason being that the object you pass to a var parameters must be exactly the type of that parameter. If FreeAndNil was declared this way you would have to cast to TObject every time you called it.
So, the designers decided that the best solution to the design problem, the least bad choice, is to use the untyped var parameter.

Why is Self assignable in Delphi?

This code in a GUI application compiles and runs:
procedure TForm1.Button1Click(Sender: TObject);
begin
Self := TForm1.Create(Owner);
end;
(tested with Delphi 6 and 2009)
why is Self writable and not read-only?
in which situations could this be useful?
Edit:
is this also possible in Delphi Prism? (I think yes it is, see here)
Update:
Delphi applications/libraries which make use of Self assignment:
python4delphi
That's not as bad as it could be. I just tested it in Delphi 2009, and it would seem that, while the Self parameter doesn't use const semantics, which you seem to be implying it should, it also doesn't use var semantics, so you can change it all you want within your method without actually losing the reference the caller holds to your object. That would be a very bad thing.
As for the reason why, one of two answers. Either a simple oversight, or what Marco suggested: to allow you to pass Self to a var parameter.
Maybe to allow passing to const or var parameters?
It could be an artefact, since system doesn't have self anywhere on the left of := sign.
Assigning to Self is so illogical and useless that this 'feature' is probably an oversight. And as with assignable constants, it's not always easy to correct such problems.
The simple advice here is: don't do it.
In reality, "Self" is just a name reference to a place on the stack that store address pointing to object in the heap. Forcing read-only on this variable is possible, apparently the designer decided not to. I believe the decision is arbitrary.
Can't see any case where this is useful, that'd merely change a value in stack. Also, changing this value can be dangerous as there is no guarantee that the behavior of the code that reference instance's member will be consistence across compiler versions.
Updated: In response to PatrickvL comment
The 'variable' "Self" is not on the
stack (to my knowledge, it never is);
Instead it's value is put in a
register (EAX to be exact) just before
a call to any object method is made. –
Nope, Self has actual address on the memory. Try this code to see for yourself.
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage(IntToStr(Integer(#Self)));
end;
procedure TForm1.Button2Click(Sender: TObject);
var
newform: TForm;
p: ^Integer;
begin
Self.Caption := 'TheOriginal';
newform := TForm.Create(nil);
try
newform.Caption := 'TheNewOne';
// The following two lines is, technically, the same as
// Self := newform;
p := Pointer(#Self);
p^ := Integer(newform);
ShowMessage(Self.Caption); // This will show 'TheNewOne' instead of 'TheOriginal'
finally
Self.Free; // Relax, this will free TheNewOne rather than TheOriginal
end;
end;
Sometimes, when you want to optimize a method for as far as you can take it (without resorting to assembly), 'Self' can be (ab)used as a 'free' variable - it could just mean the difference between using stack and using registers.
Sure, the contents of the stack are most probably already present in the CPU cache, so it should be fast to access, but registers are even faster still.
As a sidenote : I'm still missing the days when I was programming on the Amiga's Motorola 68000 and had the luxury of 16 data and 16 address registers.... I can't believe the world chose to go with the limited 4 registers of the 80x86 line of processors!
And as a final note, I choose to use Self sometimes, as the Delphi's optimizer is, well, not optimizing that well, actually. (At least, it pales compared to what trickery one can find in the various LLVM optimizers for example.) IMHO, and YMMV of course.

Resources