Initializing Records Automatically

classic Classic list List threaded Threaded
29 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Re: Re: classes initialization

Joao Morais
Jonas Maebe wrote:
> Using uninitialised variables is virtually always bad, regardless of the
> scope. And the fact that global variables are zeroed at the program
> start is afaik not defined by the Pascal standard. It's just a side
> effect of the way most operating systems work.

I think I didn't get your point. What about this piece of code:

interface

function foo: tfoo;

implementation

var
   _foo: tfoo;

function foo: tfoo;
begin
   if not assigned(_foo) then
     _foo := tfoo.create;
   result := _foo;
end;

Is it safe?

--
Joao Morais

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Re: classes initialization

Jonas Maebe-2

On 25 Mar 2008, at 14:21, Joao Morais wrote:

> Jonas Maebe wrote:
>> Using uninitialised variables is virtually always bad, regardless  
>> of the scope. And the fact that global variables are zeroed at the  
>> program start is afaik not defined by the Pascal standard. It's  
>> just a side effect of the way most operating systems work.
>
> I think I didn't get your point. What about this piece of code:
>
> interface
>
> function foo: tfoo;
>
> implementation
>
> var
>  _foo: tfoo;
>
> function foo: tfoo;
> begin
>  if not assigned(_foo) then
>    _foo := tfoo.create;
>  result := _foo;
> end;
>
> Is it safe?

It is safe on all currently supported targets (and we even go out of  
our way to ensure that it keeps working if global variables are turned  
into register variables), but it's still bad practice (and could in  
principle break one day, although it's unlikely given the backwards  
compatibility headaches that would cause).


Jonas
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
L-9
Reply | Threaded
Open this post in threaded view
|

Re: classes initialization

L-9
In reply to this post by L-9
I wrote:
> What about old borland objects (heap and stack initialization) process?
>
program test1;

type
  trec = record i: integer; end;

  tclass = class i: integer; end;
 
  tobj = object i: integer; end;
  pobj = ^Tobj;
 
procedure show;
var rec: trec; c: tclass; o: tobj; po: pobj;  
begin
  writeln('Record local:', rec.i);
  c:= tclass.create;
  new(po);
  writeln('Class local:', c.i);
  writeln('Stack Object local:', o.i);  
  writeln('Heap Object local:', po^.i);    
  c.free; c:= nil;
  dispose(po);
end;

var rec: trec; c: tclass; o: tobj; po: pobj;
begin
  show;
  writeln('Record global:', rec.i);
  c:= tclass.create;
  new(po);
  writeln('Class global:', c.i);
  writeln('Stack Object global:', o.i);    
  writeln('Heap Object global:', po^.i);      
  c.free; c:= nil;
  dispose(po);
  readln;
end.


Not a fool proof test since random values have a chance of being zero,
but it basically shows:
1. global old heap object NOT zeroed
2. local old heap object NOT zeroed
3. local class zeroed
4. global class zeroed
5. global old stack object zeroed
6. local old stack object NOT zeroed
7. global stack record zeroed
8. local stack record NOT zeroed.

I didn't bother with heap records but we can see what will happen

--
L505

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Re: classes initialization

Jonas Maebe-2

On 25 Mar 2008, at 14:40, L wrote:

> Not a fool proof test since random values have a chance of being  
> zero, but it basically shows:
> 1. global old heap object NOT zeroed
> 2. local old heap object NOT zeroed
> 3. local class zeroed
> 4. global class zeroed

The above terminology is wrong. Given your example

procedure show;
var rec: trec; c: tclass; o: tobj; po: pobj;  begin
...

What's on the stack is c (i.e., a pointer to a tclass instance) and po  
(a pointer to a tobj instance). Neither c nor po is automatically  
initialised with any value. Completely orthogonal to that is whether  
class instances or objects are initialised. As mentioned before, class  
instances are filled with zero. Object instances are just like any  
other data, so only fields of reference-counted types are initialised  
by the compiler.

The class and object constructors have no clue where the actual  
instance is located (stack, heap, shared memory, ...) nor where the  
pointer to the instance (if any) will be stored, so that does have any  
influence on their behaviour.


Jonas
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
L-9
Reply | Threaded
Open this post in threaded view
|

Re: classes initialization

L-9
In reply to this post by L-9
 >Using uninitialised variables is virtually always bad, regardless of the
 > scope. And the fact that
 > global variables are zeroed at the program start is afaik not defined
 > by the Pascal standard. It's
 > just a side effect of the way most operating systems work.

I think something like:

procedure test;
var blah: integer = 0;
begin
end;

Is useful.. i.e. initialized variables that are done on the spot.

And similarily a record could be:

procedure test;
var blah: TRec autoinit;
begin
end;

This would allow safe programming without compromising backwards
compatibility.

But... in the mean time.. a solution is to make a standard record init
procedure and do it like:

procedure test;
var blah: TRec;
begin
  init(blah);
end;

Which will be what I use for now...

And always do this by habit for safety now that I know this trick of the
fillchar and such - only ever avoiding it when needing speed (but that
is premature optimization).

I realize that local scope uninitialized vars are the way systems work
according to the system.. but we are humans and error prone humans...We
can make languages safer I think and more consistent and human friendly
at a higher level.  Humans just make so many mistakes even though
systems are supposed to work they way they are.

i.e. really it is just a convenience and a "standard good practice"
being now recommended right within the programming language...and more
safety as an option. Just as I am also a fan of reference counted
ansistrings versus using less safe pchars.. etc.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
L-9
Reply | Threaded
Open this post in threaded view
|

Re: classes initialization

L-9
I wrote:

>
> I think something like:
>
> procedure test;
> var blah: integer = 0;
> begin
> end;
>
> Is useful.. i.e. initialized variables that are done on the spot.
>
To expand on this.. not only local scope vars, but global..

var
  global: integer = 0;

I agree is much clearer than leaving it to the assumption:

// this will be zero.. bad assumption
var
  global: integer;

I wrote:
> And similarily a record could be:
>
> procedure test;
> var blah: TRec autoinit;
> begin
> end;
>
This would be a good global habit to get into also for globals:

var
  global: Trec autoinit;

or

var
  global: Trec;
begin
  init(global)
end;

The problem with the above is that sometimes the global is further away
in your code than you eyes can see, hence the inline declaring of
initialization "right while you are at it" is safer for humans.
 
Relying on global variables being zero is bad, I agree.. and they should
be iniitalized by habit.. too. Especially when one copies global code
into local code does a problem exist, if one made the assumption of the
globals being initialized then (which may have been true, but now that
they are no longer globals... problem time).


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
L-9
Reply | Threaded
Open this post in threaded view
|

Re: classes initialization

L-9
In reply to this post by L-9
I wrote:
>
> 3. local class zeroed
> 4. global class zeroed
I meant class instance zeroed

(Regarding Jonas' nitpick ;-)
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
L-9
Reply | Threaded
Open this post in threaded view
|

Re: classes initialization

L-9
In reply to this post by L-9
Joao Morais replied to Jonas with:

 >I think I didn't get your point. What about this piece of code:
 >
 >interface
 >
 >function foo: tfoo;
 >
 >implementation
 >
 >var
 > _foo: tfoo;
 >
 >function foo: tfoo;
 >begin
 > if not assigned(_foo) then
 >   _foo := tfoo.create;
 > result := _foo;
 >end;
 >
 >Is it safe?

What about this:

var
  _foo: tfoo = nil;

That way you declare it right there and then.. ensuring it is not assigned.

Hence why I think a good human practice is to always init everything
even if it psychologically affects some people in ways such as "will
this slow the program down though? Do I need to init this stuff if I am
going to init some of it later"? which is evil premature optimization
that causes bugs.

L505

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
L-9
Reply | Threaded
Open this post in threaded view
|

Re: classes initialization

L-9
In reply to this post by L-9
 > Pascal does not define any variable initialization itself - one should
 > always init all Pascal vars of any type. Doing so is an excellent
coding > habit also portable to any other language/OS - protects against
 >  low-level implementation changes.
 >
 > I never trust a side effect I didn't code myself..... 8-))


We have to stop thinking in standard pascal and think about safety and
ways to automate safety in a human matter. We are not computers, we are
humans. You can claim all you want that you will ALWAYS init all your
pascal vars...  but you are a human and you will not *always* init all
your pascal vars. This is the reason features like this have been available:

var i: integer = 0; // handy

procedure test;
var i: integer = 0; // handy
begin
end;

If you accidentally delete the init code and forget to put it back, the
above way is safer. If you accidently init something in a dangerous way
such as using FillChar on old code that now no longer works with the
newer automated types.. again this is dangerous. It may be "pascalish"
to continue to use hacks like FillChar and init() code far away from the
declaration (especially in globals).. but this is the same as a C
programmer saying that ansistrings are not C ish so we should use pchars
all the time?

Let's please stop the pascal fanboyism and consider humans, and safety.

Even Wirth has moved away from pascal greatly if you study his languages
Oberon, Modula, and a derived ComponentPascal.


L505
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
12