Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2001-09

The compiler messes up some pointers.

6 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Unknown author
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.
If you want, I can send you the full source code of my program if requested.

- Eero Tanskanen

________________________________________________________________ Ilmainen Internet @ http://www.nic.fi/

Reply by email

Jonas Maebe
to Unknown author
Show quoted text 24 lines
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)

Jonas

Reply by email

Unknown author
to Unknown author: It doesn't do it, and isn't supposed to do it. Only New() will initialize any memory for…
Show quoted text 6 lines
On Sat, 22 Sep 2001, Jonas Maebe wrote: > > On Sat, 22 Sep 2001 wrote: > > > I have a problem where FPC modifies a pointer without me

instructing it

Show quoted text 10 lines
> > 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 :

Show quoted text 7 lines
> > > > 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

Show quoted text 13 lines
> 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?

________________________________________________________________ Ilmainen Internet @ http://www.nic.fi/

Reply by email

Barry Kelly
to Unknown author
Show quoted text 13 lines
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?

Constant strings have a refcount of -1.

-- Barry

If you're not part of the solution, you're part of the precipitate. Team JEDI: http://www.delphi-jedi.org NNQ - Quoting Style in Newsgroup Postings http://web.infoave.net/~dcalhoun/nnq/nquote.html

Reply by email

Unknown author
to Jonas Maebe: You are doing very dangerous things. Ansistrings are reference counted, which measn that…
Jonas Maebe wrote 39 lines
On Sat, 22 Sep 2001 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.

Michael.

Reply by email

Unknown author
to Unknown author: instructing it of that I rows : (the can't but I kind of your corruption. I agree with…
Show quoted text 80 lines
wrote: > > On Sat, 22 Sep 2001, Jonas Maebe wrote: > > > > On Sat, 22 Sep 2001 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.

Reply by email