Sign in Join

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

Mailing lists / fpc-pascal / 2012-04

Problems with assigning pointers

10 messages · 8 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 some issues when assigning a pointer to a pointer variable. Consider this:

 TVertex = record
 x: double;
 y: double;
 end;
PVertex = ^TVertex;
 TEdge = record
 v1: PVertex;
 v2: PVertex;
 end;

I have assigned a value to a vertex variable. In my code I have an array of TEdge. When I try to assign a vertex to the edge element in the array the x value suddenly is changed to 3e-308 (or something similar). I don't understand why, perhaps someone could help me to figure this out.The code I'm using to assign the value is shown below. To my knowledge assigning a pointer this way is perfectly legal not?

procedure add_edge(v1, v2: PVertex);
begin
 inc(edge_count);
SetLength(edge_list, edge_count);
 edge_list[edge_count - 1].v1 := v1;
//

Reply by email

Mattias Gaertner
to Unknown author
Show quoted text 34 lines
I have some issues when assigning a pointer to a pointer variable. Consider this: TVertex = record x: double; y: double; end; PVertex = ^TVertex; TEdge = record v1: PVertex; v2: PVertex; end; I have assigned a value to a vertex variable. In my code I have an array of TEdge. When I try to assign a vertex to the edge element in the array the x value suddenly is changed to 3e-308 (or something similar). I don't understand why, perhaps someone could help me to figure this out.The code I'm using to assign the value is shown below. To my knowledge assigning a pointer this way is perfectly legal not? procedure add_edge(v1, v2: PVertex); begin inc(edge_count); SetLength(edge_list, edge_count); edge_list[edge_count - 1].v1 := v1; //

Code looks ok. The bug is probably in the code you didn't send. Maybe your vertices are on the stack?

Mattias

Reply by email

leledumbo
to Unknown author: I have some issues when assigning a pointer to a pointer variable. Consider this: TVertex…

Can't reproduce with the following program:

type
  TVertex = record
    x: double;
    y: double;
  end;
  PVertex = ^TVertex;
  TEdge = record
    v1: PVertex;
    v2: PVertex;
  end;
var
  edge_count: LongWord = 0;
  edge_list: array of TEdge;
procedure add_edge(v1, v2: PVertex);
begin
  inc(edge_count);
  SetLength(edge_list, edge_count);
  WriteLn(v1^.x:1:4,' ',v1^.y:1:4); // this
  edge_list[edge_count - 1].v1 := v1;
  WriteLn(v1^.x:1:4,' ',v1^.y:1:4); // outputs the same thing as this
  edge_list[edge_count - 1].v2 := v2;
end;
var
  a: PVertex;
begin
  New(a);
  a^.x := 2.56;
  a^.y := 3.14;
  add_edge(a,nil);
  Dispose(a);
end.
View this message in context: http://free-pascal-general.1045716.n5.nabble.com/Problems-with-assigning-pointers-tp5630400p5630539.html Sent from the Free Pascal - General mailing list .

Reply by email

Jürgen Hestermann
to Unknown author: I have some issues when assigning a pointer to a pointer variable. Consider this: TVertex…
edge_list[edge_count - 1].v1 := v1; //<---- after this line the

value of v1^.x suddenly is changed!!??!!

Could it be that you do something else with "edge_list" before the assignment?
Keep in mind that "edge_list" is a dynamic array and therefore a pointer (with
automatic dereferencing by the square brackets).
If you somehow changed this pointer (without realizing it) it could be that the
assignment overwrites v1 (or the data it points to).

But pointer are always a source of errors.
Only use them when it's unavoidable.
If you can do the same without pointers then don't use them. ;-)

Reply by email

Alberto Narduzzi
to Jürgen Hestermann
But pointer are always a source of errors. Only use them when it's unavoidable. If you can do the same without pointers then don't use them. ;-)

Of course, if you just use pointers because others do, indeed they might be...
No comment.

A.

Reply by email

Darius Blaszyk
to leledumbo: Can't reproduce with the following program: type TVertex = record x: double; y: double;…

Here's a minimal example that has the bug. First of all the first output is wrong as it says 0,50 instead of 20,50 (so the x item is overwritten). The second printed output differs from the first, so again the x item is overwritten. I'm clueless.

program test;
{$mode objfpc}{$H+}
type
  TVertex = record
    x: double;
    y: double;
  end;
  PVertex = ^TVertex;
  TEdge = record
    v1: PVertex;
    v2: PVertex;
  end;
var
  vert_count: integer = 0;
  vert_list: array of TVertex;
  edge_count: integer = 0;
  edge_list: array of TEdge;
function add_vert(x, y: double): PVertex;
begin
  Inc(vert_count);
  SetLength(vert_list, vert_count);
  vert_list[vert_count - 1].x := x;
  vert_list[vert_count - 1].y := y;
  Result := @vert_list[vert_count - 1];
end;
procedure add_edge(v1, v2: PVertex);
begin
  Inc(edge_count);
  SetLength(edge_list, edge_count);
  WriteLn(v1^.x,' ',v1^.y); // this
  edge_list[edge_count - 1].v1 := v1;
  WriteLn(v1^.x,' ',v1^.y); // outputs the same thing as this
  edge_list[edge_count - 1].v2 := v2;
end;
var
  v1: PVertex;
  v2: PVertex;
begin
  v1 := add_vert(20, 50);
  v2 := add_vert(220, 50);
  add_edge(v1, v2);
  readln;
end.

Regards, Darius

leledumbo wrote 45 lines
Can't reproduce with the following program: type TVertex = record x: double; y: double; end; PVertex = ^TVertex; TEdge = record v1: PVertex; v2: PVertex; end; var edge_count: LongWord = 0; edge_list: array of TEdge; procedure add_edge(v1, v2: PVertex); begin inc(edge_count); SetLength(edge_list, edge_count); WriteLn(v1^.x:1:4,' ',v1^.y:1:4); // this edge_list[edge_count - 1].v1 := v1; WriteLn(v1^.x:1:4,' ',v1^.y:1:4); // outputs the same thing as this edge_list[edge_count - 1].v2 := v2; end; var a: PVertex; begin New(a); a^.x := 2.56; a^.y := 3.14; add_edge(a,nil); Dispose(a); end. -- View this message in context: http://free-pascal-general.1045716.n5.nabble.com/Problems-with-assigning-pointers-tp5630400p5630539.html Sent from the Free Pascal - General mailing list . _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Vincent Snijders
to Darius Blaszyk

Op 10 april 2012 22:06 heeft Darius Blaszyk
het volgende geschreven:

Show quoted text 33 lines
Here's a minimal example that has the bug. First of all the first output is wrong as it says 0,50 instead of 20,50 (so the x item is overwritten). The second printed output differs from the first, so again the x item is overwritten. I'm clueless. program test; {$mode objfpc}{$H+} type  TVertex = record    x: double;    y: double;  end;  PVertex = ^TVertex;  TEdge = record    v1: PVertex;    v2: PVertex;  end; var  vert_count: integer = 0;  vert_list: array of TVertex;  edge_count: integer = 0;  edge_list: array of TEdge; function add_vert(x, y: double): PVertex; begin  Inc(vert_count);  SetLength(vert_list, vert_count);  vert_list[vert_count - 1].x := x;  vert_list[vert_count - 1].y := y;  Result := @vert_list[vert_count - 1];

I think this is not correct. If you increase the size of vert_list, then the array may be relocated and Result isn't a valid pointer anymore.

Show quoted text 26 lines
end; procedure add_edge(v1, v2: PVertex); begin  Inc(edge_count);  SetLength(edge_list, edge_count);  WriteLn(v1^.x,' ',v1^.y); // this  edge_list[edge_count - 1].v1 := v1;  WriteLn(v1^.x,' ',v1^.y); // outputs the same thing as this  edge_list[edge_count - 1].v2 := v2; end; var  v1: PVertex;  v2: PVertex; begin  v1 := add_vert(20, 50);  v2 := add_vert(220, 50);  add_edge(v1, v2);  readln; end.

Vincent

Reply by email

Sven Barth
to Vincent Snijders
Vincent Snijders wrote 40 lines
Op 10 april 2012 22:06 heeft Darius Blaszyk het volgende geschreven: > Here's a minimal example that has the bug. First of all the first output is wrong as it says 0,50 instead of 20,50 (so the x item is overwritten). The second printed output differs from the first, so again the x item is overwritten. I'm clueless. > > program test; > > {$mode objfpc}{$H+} > > type > TVertex = record > x: double; > y: double; > end; > PVertex = ^TVertex; > > TEdge = record > v1: PVertex; > v2: PVertex; > end; > > var > vert_count: integer = 0; > vert_list: array of TVertex; > edge_count: integer = 0; > edge_list: array of TEdge; > > function add_vert(x, y: double): PVertex; > begin > Inc(vert_count); > SetLength(vert_list, vert_count); > > vert_list[vert_count - 1].x := x; > vert_list[vert_count - 1].y := y; > > Result := @vert_list[vert_count - 1]; I think this is not correct. If you increase the size of vert_list, then the array may be relocated and Result isn't a valid pointer anymore.

This is indeed the problem.

Show quoted text 20 lines
> end; > > procedure add_edge(v1, v2: PVertex); > begin > Inc(edge_count); > SetLength(edge_list, edge_count); > > WriteLn(v1^.x,' ',v1^.y); // this > edge_list[edge_count - 1].v1 := v1; > WriteLn(v1^.x,' ',v1^.y); // outputs the same thing as this > edge_list[edge_count - 1].v2 := v2; > end; > > var > v1: PVertex; > v2: PVertex; > > begin > v1 := add_vert(20, 50); > v2 := add_vert(220, 50);

Your pointer to v1 is already invalid here, because the second "add_vert" already changed the location of the array and thus the new pointer locations are also different.

Show quoted text 6 lines
> > add_edge(v1, v2); > > readln; > end. >

A better solution if you want to keep the "vertex array" would be to have an array of "PVertex" instead of "TVertex". You then need to do a "New(Result)" in your "add_vertex" function and add that "Result" to the enlarged array. Similiary you'll need to do a "Dispose(...)" in some "remove_vertex" procedure.

Regards,
Sven

Reply by email

Jürgen Hestermann
to Vincent Snijders: Op 10 april 2012 22:06 heeft Darius Blaszyk het volgende geschreven: I think this is not…
Show quoted text 11 lines
> type > TVertex = record > x: double; > y: double; > end; > PVertex = ^TVertex; > > TEdge = record > v1: PVertex; > v2: PVertex; > end;

.
.

Show quoted text 5 lines
> Result := @vert_list[vert_count - 1]; I think this is not correct. If you increase the size of vert_list, then the array may be relocated and Result isn't a valid pointer anymore.

True.

I think it would be better to change the type of "vert_list" to

type vert_list : array of PVertex;

This would have two advantages:

1.) Array sorting and reallocation would be faster because only a pointer to each element is stored in the array and if the element type is changed (increases in size) it would not affect performance.

2.) Assignments as "Result := @vert_list[vert_count - 1];" would convert
to "Result := vert_list[vert_count - 1];" and therefore references to
the element itself would be unaffected by array resorting.

Reply by email

Unknown author
to Sven Barth: This is indeed the problem. Your pointer to v1 is already invalid here, because the second

Hi Sven en Vincent,

Thanks for your hints. Indeed the dynamic
array was the problem. I have now replaced it by a linked list of verts/edges/faces. It now works perfectly.

Regards, Darius

Sven Barth wrote
Am 10.04.2012 22:16, schrieb Vincent

Snijders:

> Op 10 april 2012 22:06 heeft Darius Blaszyk het volgende

geschreven:

> >> Here's a minimal example that has the bug. First of
all the first output is wrong as it says 0,50 instead of 20,50 (so the x
item is overwritten). The second printed output differs from the first,
so again the x item is overwritten. I'm clueless. program test; {$mode
objfpc}{$H+} type TVertex = record x: double; y: double; end; PVertex =
^TVertex; TEdge = record v1: PVertex; v2: PVertex; end; var vert_count:
integer = 0; vert_list: array of TVertex; edge_count: integer = 0;
edge_list: array of TEdge; function add_vert(x, y: double): PVertex;
begin Inc(vert_count); SetLength(vert_list, vert_count);
vert_list[vert_count - 1].x := x; vert_list[vert_count - 1].y := y;
Result := @vert_list[vert_count - 1];
> I think this is not correct. If

you increase the size of vert_list, then the array may be relocated and Result isn't a valid pointer anymore.

Show quoted text 5 lines
This is indeed the problem. >> end; procedure add_edge(v1, v2: PVertex); begin Inc(edge_count);
SetLength(edge_list, edge_count); WriteLn(v1^.x,' ',v1^.y); // this
edge_list[edge_count - 1].v1 := v1; WriteLn(v1^.x,' ',v1^.y); // outputs
the same thing as this edge_list[edge_count - 1].v2 := v2; end; var v1:
PVertex; v2: PVertex; begin v1 := add_vert(20, 50); v2 := add_vert(220,
50);
Show quoted text 7 lines
Your pointer to v1 is already invalid here, because the second "add_vert" already changed the location of the array and thus the new pointer locations are also different. add_edge(v1, v2); readln;
end.
> "TVertex". You then need to do a "New(Result)" in your

"add_vertex" function and add that "Result" to the enlarged array. Similiary you'll need to do a

" in some "remove_vertex" procedure.

Regards, Sven _______________________________________________ fpc-pascal maillist - [2]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal [3]

Links:
------
[1]
[2]

[3]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email