Reputation: 4663
I have a class
type
TLoadOption = class
private
FAutoSearch: Boolean;
public
property AutoSearch: Boolean read FAutoSearch write FAutoSearch;
end;
In one of the functions i am creating the object of the class in stack
procedure MyView.InitializeForm(const aMsg: MyMsg);
//---------------------------------------------------------------------------
var
Options: TLoadOption;
begin
if aMsg.OptionalObject <> nil then
Options := aMsg.OptionalObject as TLoadOption;
if Assigned(Options) and Options.AutoSearch then
DoRefresh;
end;
I am not passing anything in aMsg so ideally Options is not set.
In Delphi XE by default Options is set as nil and so this DoRefresh is not called but when i execute the same code in Delpi XE4 the options is initialized with some random value and AutoSearch becomes true always and it results in calling this DoRefresh function which is undesired.
I am wondering if there are any compiler options that set default values to uninitialized variable. My only solution as of now is like this
procedure MyView.InitializeForm(const aMsg: MyMsg);
//---------------------------------------------------------------------------
var
Options: TLoadOption;
begin
Options := nil;
if aMsg.OptionalObject <> nil then
Options := aMsg.OptionalObject as TLoadOption;
if Assigned(Options) and Options.AutoSearch then
DoRefresh;
end;
is this a correct way?
Upvotes: 6
Views: 621
Reputation: 21738
As the other answers already said the local variable is not initialized.
However what I like to add here is that as
is nil safe. That means you don't need to check if aMsg.OptionalObject
is assigned. You can just write:
var
Options: TLoadOption;
begin
Options := aMsg.OptionalObject as TLoadOption;
if Assigned(Options) and Options.AutoSearch then
DoRefresh;
end;
Keep in mind that it will throw an exception if OptionalObject does not inherit from TLoadOption. The code looks as that is always the case. So if you are sure about that you can use a hardcast:
begin
if Assigned(aMsg.OptionalObject) and TLoadOption(aMsg.OptionalObject).AutoSearch then
DoRefresh;
end;
Upvotes: 7
Reputation: 1204
You don't need local var at all.
procedure MyView.InitializeForm(const aMsg: MyMsg);
begin
if Assigned(aMsg.OptionalObject)
and (aMsg.OptionalObject is TLoadOption)
and (aMsg.OptionalObject as TLoadOption).AutoSearch
then
DoRefresh;
end;
Upvotes: 1
Reputation: 34909
A local class is not initialized. You need to set it to nil before testing its assignment.
See Are delphi variables initialized with a value by default?.
Only local reference-counted variables are initialized (example: String,dynamic arrays,interface,variants).
If you are targeting mobile platforms, where ARC (automatic reference counting) is introduced, classes are reference counted though. See Automatic Reference Counting in Delphi Mobile Compilers.
Upvotes: 11
Reputation: 31433
No. Assuming that TLoadOption
is an object (unmanaged reference type) you have to initialize local variables yourself. There is no option to have them initialized for you. Local variables for reference types (except for managed types like strings, etc) that are uninitialized will always contain whatever garbage data was in that location on the stack. This makes use of Assigned
impossible.
You might just simplify your code a bit, but this is about as short as it can get.
var
Options: TLoadOption;
begin
if aMsg.OptionalObject <> nil then begin
Options := aMsg.OptionalObject as TLoadOption;
if Options.AutoSearch then DoRefresh;
end;
end;
Upvotes: 6
Reputation: 613163
Options
is a local variable, of a non-managed type. Which means that it is not initialized. It can have any value until you initialize it. If the variable sometimes happens to have the value nil
without you having initialized it, then that's just unlucky for you.
You must initialize local variables before attempting to read them.
Upvotes: 3