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 := TObject(Obj); Pointer(…

Delphi Nullable with Custom Managed Records

Published with special permission from Embarcadero - this post writes about pre-release Delphi version where everything is subject to change until finally released.

Nullables are a rather simple concept. All you need is a value, and some flag that will tell you whether or not the value has been explicitly set or not.
type TNullable<T> = record private FHasValue: boolean; FValue: T; function GetValue: T; procedure SetValue(AValue: T); public property HasValue: boolean read FHasValue; property Value: T read GetValue write SetValue; end; function TNullable<T>.GetValue: T; begin if FHasValue then Result := FValue else raise Exception.Create('Invalid operation, Nullable type has no value'); end; procedure TNullable<T>.SetValue(AValue: T); begin FHasValue := True; FValue := AValue; end;
Plain and simple. But then you have the fact that records are not automatically initialized and that your FHasValue boolean can ho…

Listen to the Memory Manager

Let's say you have a nice, working Delphi application. One fine day, for no reason whatsoever, you decide to run your fine and bug free application with FastMM in full debug mode. Just for fun... and suddenly, out of the blue, the app starts crashing with an AV reading of address 0x80808088. What is going on... ????

When a seemingly working application suddenly starts misbehaving, the first instinct would be to look at the latest code change in searching for clues. In the above case, the only change was turning on FastMM debug mode. Could this be a bug in FastMM?

While all software has bugs and it is perfectly possible that FastMM has bugs, too, it is highly unlikely that this is FastMM's fault.

If turning on the CatchUseOfFreedInterfaces define in FastMM configuration shows an attempt to use an interface on a freed object, you have found the culprit. It may require further debugging and inspecting the code, but at least you will know what to look for.

One of the "problem…

Unified Memory Management - Coming with 10.4 Beta

As announced on previous roadmaps, the 10.4 release of Delphi is planned to have unified memory management. That means retiring the ARC compiler on mobile platforms, which will now operate under the same good old manual memory management model that originated on Windows.

Unification is good. Completely different memory management models require slightly different code. That alone breaks the promise of a single code base for all platforms. In reality, if you need to target platforms with different memory management models you will find yourself coding under the requirements of manual memory management where ARC will only throw you some curveballs. Constrained ARC is bad ARC, it is not useful, it cannot unleash its full power.

On one side I am happy because of unification, on the other I am sad to see the ARC compiler go. It had great potential and was mostly brought down by unoptimized RTL/FMX code that was written for manual memory management. There is a whole lot of code that could b…

Self destructing object instance

Using reference counting classes always requires some caution. You have to pay attention to reference cycles, using interface reference for referencing such object instances, not calling FreeAndNil and more... it is quite a list...

But every once in a while, new ways of shooting yourself in the foot keep popping up... So here goes the story...

I have two reference counted classes that hold reference to each other instances. One of those references is marked as [weak] to prevent creating strong reference cycle.

type TFoo = class(TInterfacedObject) private [weak] FRef: IInterface; public constructor Create(const ARef: IInterface); end; TBar = class(TInterfacedObject) private FFoo: IInterface; public constructor Create; virtual; destructor Destroy; override; procedure AfterConstruction; override; end; constructor TFoo.Create(const ARef: IInterface); begin inheri…

Rio 10.3.3 Update

RAD Studio 10.3.3 update is live.

Just like previous 10.3.2 update got big feature in macOS 64bit platform, 10.3.3 brings long awaited Android 64bit platform support.

Adding 64bit Android platform is pretty straightforward.

You need to add 64bit SDK - make sure it uses the same base paths as 32bit SDK, open your project and 64bit Android will be automatically added to the platform list.

You need to make sure that all deployed resources for 32bit platform are also included for 64bit platform and you are ready to go.

If you want to test application on the device, you have to make sure that your device actually has 64bit Android OS. Even some newer low end devices still use 32bit OS despite the fact they do have 64bit CPUs. If you are about to purchase new device, double check OS bitness.

If your device does not have 64bit OS and you run 64bit Delphi application on it, it will show message "64-bit OS device required".

Unfortunately, 64bit Android debugger has some issues with p…