Posts

Showing posts with the label FreeAndNil

FreeAndNil Debate: Thread Safety

One of the topics raised in yesterday's FreeAndNil debate was using FreeAndNil in multi-threaded code for avoiding access to a dangling reference when multiple threads are accessing and using the same object instance. Problem is that FreeAndNil is not thread-safe and cannot be used to achieve thread safety. You cannot call FreeAndNil on a shared object reference in one thread and then use if Assigned  in another to check whether object is still alive and then do something with that object. Your second thread can pass the if Assigned check and start working with the object while the first thread can destroy that object at any point. There is no mechanism in the FreeAndNil and if Assigned check that can prevent that. If you need to use shared object instance in such manner you need to use locking mechanism and lock all access, in all threads, to such an object. If you use locking mechanism, then you can use FreeAndNil in one thread and if Assigned check in another. I ment...

Pass the Dog, Get the Cat

This story begins with the FreeAndNil procedure, why its signature could not have a typed var parameter, why we can only pass variables declared as TObject to such procedures, and why the compiler refuses to compile if we try passing any other variable type even if it is a descendant of TObject . procedure FreeAndNil(var Obj); So why does the compiler enforce this behavior? If we take a look at the FreeAndNil implementation and imagine it with a typed var parameter, it may seem that the compiler is throwing us curve balls for nothing. There is nothing we do inside that procedure that would warrant a compiler error for passing TObject descendant types: assigning variable to another TObject variable - pass assigning nil to original variable - pass freeing original object instance stored in temporary variable - pass procedure FreeAndNil(var Obj: TObject); var Temp: TObject; begin Temp := TObject(Obj); Pointer(Obj) := nil; Temp.Free; end; var Obj: TSomeObject...

Magic behind FreeAndNil

Delphi 10.4 Sydney brings one small but rather significant change. A change in the signature of the FreeAndNil procedure from procedure FreeAndNil(var Obj); inline; to procedure FreeAndNil(const [ref] Obj: TObject); inline; Wait, const means the variable is passed as a constant and cannot be changed from within the procedure. But the whole point of FreeAndNil is to change the passed object variable to nil. What kind of sorcery is this? Let's start from the beginning and the old FreeAndNil procedure, its purpose and implementation. The purpose of FreeAndNil is to simplify the following code sequence: Foo.Free; Foo := nil; While the actual implementation of FreeAndNil is slightly different, and it will first nil the reference and then Free the object instance (temporarily preserved in a local variable), that slight difference is not relevant for discussing the signature of FreeAndNil . procedure FreeAndNil(var Obj); var Temp: TObject; begin Temp := TOb...