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
Freeon a null reference is always safe. Go look in the implementation ofTObject.Freeto 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 callsFree, but if it’s already transfered ownership, then it ends up callingFreeon a null reference, and there’s no harm done. This code is what transfers ownership:The way I would write a factory function would do away with the separate
Connectionvariable. I’d construct the result directly inResult, but free it if there were an exception, like this:That has the same effect.