[fpc-pascal] Pascal pointer life cycle

spir ☣ denis.spir at gmail.com
Wed May 5 12:28:30 CEST 2010


Hello,

First, I found a very good introduction material to pointers at http://cslibrary.stanford.edu/. The author, "Nick Parlante" (nickname?) really has a great pedagogical talent.

Below some code and output tracing a typical pointer's life cycle:

======= code =======
procedure PointerLifeCycle0();
var
    p : PInteger;		// ^Integer
begin
    writeln('startup:');
//    writeln('v:',p^);            // Access Violation
    writeln('p:',longword(p));    // warning not initialized

    writeln('allocation:');
    new(p);
    writeln('p:',longword(p));    // address
    writeln('v:',p^);            // random ; no error

    writeln('valuation:');
    p^ := 1;
    writeln('v:',p^);            // 1
    
    writeln('disposal:');
    dispose(p);
    writeln('p:',longword(p));    // meaningless ; no error
    writeln('v:',p^);            // trash ; no error

    writeln('nil-ization:');
    p := nil;
    writeln('p:',longword(p));    // 0
//    writeln('v:',p^);            // Access Violation
end;
====== output ======
startup:
p:3215995332
allocation:
p:9105488
v:9105500
valuation:
v:1
disposal:
p:9105488
v:9105500
nil-ization:
p:0
====================

So, I have 3 questions:
-1- Why isn't an unallocated pointer nil?
-2- Why is it at all possible to allocate a pointer without setting the target's value? In other word why doesn't new() take a second argument, value. Or, why not have this argument optional and recommend its use?
-3- Why is it at all possible to deallocate a pointer without "nil-izing" it? Why not have dispose() set it to nil?

Consequently, I wrote 2 procs setPointer and resetPointer:

======= code =======
procedure setPointer(var p:PInteger ; v:Integer);
begin
    new(p);
    p^ := v;
end;
procedure resetPointer(var p:PInteger ; v:Integer);
begin
    dispose(p);
    p := nil;
end;
procedure PointerLifeCycle1();
var
    p : PInteger = nil;            // manual...
begin
    writeln;
    writeln('startup:');
    write('p:',longword(p));    // warning not initialized
    writeln(' (may be automatic)');

    writeln('allocation & valuation:');
    setPointer(p, 1);
    writeln('p:',longword(p));    // address
    writeln('v:',p^);            // random ; no error

    writeln('disposal & nil-ization:');
    resetPointer(p, 1);
    writeln('p:',longword(p));    // meaningless ; no error
//    writeln('v:',p^);            // Access Violation
end;
====== output ======
startup:
p:0 (may be automatic)
allocation & valuation:
p:9105488
v:1
disposal & nil-ization:
p:0
====================

(Unfortunately, I cannot have p=nil automatic at startup.)
Is such a behaviour consistent and desirable? If yes, why does Pascal let dangerous pointers live? If not, what are the use cases for possibly unsafe pointers? And why not have builtin procs offer this behaviour anyway, when possible?
I won't use the above procedures because of the call (and value copy (*)) overhead --since my future code will do nearly everything via pointers. But I would love to have this semantics builtin (and then run at machine code speed, with no call and no copy).

Denis

(*) If the value is passed by ref, then the caller must have it stored in a variable.
________________________________

vit esse estrany ☣

spir.wikidot.com



More information about the fpc-pascal mailing list