[fpc-pascal]The compiler messes up some pointers.
Michael.VanCanneyt at Wisa.be
Michael.VanCanneyt at Wisa.be
Sun Sep 23 03:12:32 CEST 2001
On Sat, 22 Sep 2001 yendor at nic.fi wrote:
>
>
>
> Michael.VanCanneyt at Wisa.be wrote:
> >
> > On Sat, 22 Sep 2001, Jonas Maebe wrote:
> > >
> > > On Sat, 22 Sep 2001 yendor at nic.fi wrote:
> > >
> > > > I have a problem where FPC modifies a pointer without me
> instructing it
> > > > to do so.
> > > > With stucture :
> > > > Type
> > > > PAnsiString = ^AnsiString;
> > > > PPAnsiString = ^PAnsiString;
> > > >
> > > > Var
> > > > RowAP : ^PPAnsiString;
> > > >
> > > > I first create two rows (that are the ansistrings in a pointer of array
> of
> > > > pointer of ansistring structure) and set some data into them. After
> that I
> > > > add one row between these two and initialize it with exactly these
> rows :
> > > >
> > > > GetMem(RowAP^[1], SizeOf(AnsiString));
> > > > Writeln(LongInt(RowAP^[2]));
> > > > RowAP^[1]^ := 'a';
> > > > Writeln(LongInt(RowAP^[2]));
> > > >
> > > > The program outputs two lines that are : "4284808" and "4284807"
> (the
> > > > values differ of course, but not the difference) which isn't right. I
> can't
> > > > reproduce this in other programs (haven't tried very extensively)
> but I
> > > > don't think that I could ever mess up my program to produce this
> kind of
> > > > thing.
> > >
> > > You are doing very dangerous things. Ansistrings are reference
> counted,
> > > which measn that the compiler normally does a lot of things behind
> your
> > > back. With the above construction, it fails to do these things...
> > >
> > > You have to intialize all memory you allocate this way for storing
> > > ansistrings in explcitely with 0 before storing an ansistring in them, or
> > > you may get random memory corruption.
> > >
> > > I don't know whether the compile should do that automatically in this
> > > case, it's possible it should (but it definitely doesn't currently)
> >
> > It doesn't do it, and isn't supposed to do it. Only New() will initialize
> > any memory for use with ansistrings. When using GetMem() you should
> > explicitly zero out any memory that should be occuped by ansistrings
> > before using it. Failing to do so may and will result in memory
> corruption.
> > In the above case, this should definitely be done.
>
> I agree with Michael about that. The problem is (at least I think that it's)
> that most pascal programmers don't think ansistring as a pointer. Also
> note that you can't do a New(AnsiStringVar); and implementing this will
> require it to properly handle the reference count.
>
> By the way. My
> Var
> TempL : ^LongInt;
> A : AnsiString;
> B : AnsiString;
> Begin
> A := 'Blaah3';
> B := A;
> TempL := Pointer(A);
> Dec(TempL);
> Writeln(TempL^);
> End.
> - proggie returns -1. Is reference counting working?
Yes.
This is an optimization by FPC; constant strings always have item count
-1, whatever the number of strings pointing to it. All other routines
(adding assignment etc) take care of this.
Try
A := 'Blaah3';
A := A+'3haalB'b
B:=A;
Then you should get 3. 3, not 2 because the temporary variable used to
do the assignment is only cleaned when the program reaches the 'end.'
statement.
Doing however:
var
A : AnsiString;
procedure test (Var b : AnsiString);
Begin
A := 'Blaah3';
A := A + '3haalB';
B := A;
end;
var
B : AnsiString;
TempL : ^LongInt;
begin
test(B);
TempL := Pointer(B);
Dec(TempL);
Writeln(TempL^);
End.
will print 2. Moving the declaration of A into the procedure test will
print 1.
Michael.
More information about the fpc-pascal
mailing list