[fpc-pascal] Read-only global references

Marcos Douglas md at delfire.net
Sun Mar 6 01:57:41 CET 2011


On Sat, Mar 5, 2011 at 8:15 PM, Marcos Douglas <md at delfire.net> wrote:
> On Sat, Mar 5, 2011 at 7:05 PM, Mark Morgan Lloyd
> <markMLl.fpc-pascal at telemetry.co.uk> wrote:
>> Marcos Douglas wrote:
>>>
>>> On Sat, Mar 5, 2011 at 8:24 AM, Mark Morgan Lloyd
>>> <markMLl.fpc-pascal at telemetry.co.uk> wrote:
>>>>
>>>> Where a unit exports an instance of an object, what's best practice for
>>>> making this read-only? I'm referring to the object reference itself here,
>>>> not properties of the object.
>>>>
>>>> Where I've done this in the past I've used a function:
>>>>
>>>> interface
>>>>
>>>> function InitText: TFormattedString;
>>>>
>>>> implementation
>>>>
>>>> var     xInitText: TFormattedString= nil;
>>>>
>>>> function InitText: TFormattedString;
>>>>
>>>> begin
>>>>  result := xInitText
>>>> end { InitText } ;
>>>>
>>>> Is there a better way using e.g. global properties that doesn't
>>>> necessitate
>>>> both a property and an explicit function?
>>>>
>>>> property InitText: TFormattedString read xInitText;
>>>>
>>>> The obvious problem here is that xInitText is a forward reference to an
>>>> unexported variable.
>>>
>>> Make a function to return a global variable does not make it read only.
>>> If I use your function like this:
>>> o := InitText;
>>> o := nil;  //this is the same xInitText = nil
>>
>> Disagree. You are changing the value of o, not of xInitText. xInitText is
>> initialised once somewhere in the unit exporting it, subsequently its
>> properties etc. can be used elsewhere e.g. InitText.AppendFormatted(...).
>
> You right... but not TOTALY.
> I made a little program to explain that, but now I'm confusing, see:
>
> program ref;
>
> {$mode objfpc}{$H+}
>
> uses
>  sysutils;
>
> type
>  TObj = class
>  public
>    i: integer;
>  end;
>
> var
>  o1: TObj = nil;
>  o2: TObj = nil;
>
> function getobj: TObj;
> begin
>  if not Assigned(o1) then
>    o1 := TObj.Create;
>  o1.i := 1;
>  result := o1;
> end;
>
> begin
>  o1 := getobj;
>  o2 := o1;
>  writeln('o1.i: ', o1.i);
>  writeln('o2.i: ', o2.i);
>  writeln('o2.i change to 2');
>  o2.i := 2;
>  writeln('o1.i = 2 too?": ', o1.i = 2);
>  writeln('Destroy o2');
>  o2.Free;
>  writeln('o1.i still exists?: ', Assigned(o1), ' so, write o1.i: ', o1.i);
>  writeln('o1.i change to 3');
>  o1.i := 3;
>  writeln('o1.i: ', o1.i);
>  try
>    o1.Free;
>  except
>    on e: Exception do
>      writeln(e.Message);
>  end;
>  readln;
> end.
>
> The o1 variable still exists, even after o2 was destroed! But o2 point to o1...
> The variable o1 exists, but I can't destroy it! Why??
>
> I test on Lazarus and Delphi 7.
> The only diference is in this line:
>  writeln('o1.i still exists?: ', Assigned(o1), ' so, write o1.i: ', o1.i);
>
> In Lazarus, the result is:
> TRUE | 0
>
> In Delphi, the result is:
> TRUE | 2
>
> Again... Why??

This occurs because I use the "pointer of memory" of property "i"  and
the compiler ignore the instance of object?
I don't understand... if o1==o2 and o1 was released (Free and Nil),
why I can continue using o2 if it points to the same memory, i.e., o1?
And why I can't destroy it?

I think the property "i" continue existing and, because that, I can
continue using "i" property through o2 variable. Is that right?


Marcos Douglas



More information about the fpc-pascal mailing list