Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 更改指针值的Pascal指针_Delphi_Pointers_Pascal - Fatal编程技术网

Delphi 更改指针值的Pascal指针

Delphi 更改指针值的Pascal指针,delphi,pointers,pascal,Delphi,Pointers,Pascal,我是Pascal的新手,目前正在使用指针。 我有两条记录,其中一条包含指向另一条记录类型的两个指针 type WaypointRef = ^Waypoint; PathRef = ^Path; Waypoint = record id: integer; Name: string; pathRefs: array of PathRef; end; Path = record distance: integer; WaypointR

我是Pascal的新手,目前正在使用指针。 我有两条记录,其中一条包含指向另一条记录类型的两个指针

type
  WaypointRef = ^Waypoint;

  PathRef = ^Path;

  Waypoint = record
    id: integer;
    Name: string;
    pathRefs: array of PathRef;
  end;

  Path = record
    distance: integer;
    WaypointRefA, WaypointRefB: WaypointRef;
  end; 
所有航路点都保存在一个数组中。 现在,当我试图读出路径的值时,我得到了神秘的结果:

writeln(waypoints[0].pathRefs[0]^.distance);
writeln(waypoints[1].pathRefs[0]^.distance);
两者应打印相同的值,但它们不打印。 然而,更神秘的是,即使我尝试以下方法:

writeln(waypoints[0].pathRefs[0]^.distance);
writeln(waypoints[0].pathRefs[0]^.distance);
writeln(waypoints[0].pathRefs[0]^.distance);
我得到两个不同的值。正确的一个-173-首先,然后所有时间后2

waypoints[0].pathRefs[0]^
总是指向同一个地址,所以我很困惑。我希望有人知道这个问题

编辑:2似乎是默认值,因为如果在创建路径时未将任何值保存到距离,它也会返回2

EDIT2:这里是航路点和路径创建的代码。我想一定是失败了。我现在可能会因为程序中的程序而混淆设计。我只是在试验

procedure buildWaypoint(Name: string);

  procedure addWaypoint(w: Waypoint);
  var
    lngth: integer;
  begin
    lngth := Length(waypoints);
    SetLength(waypoints, lngth + 1);
    waypoints[lngth] := w;
  end;

var
  w: Waypoint;
begin
  w.id := id;
  id := id + 1;

  w.Name := Name;
  addWaypoint(w);
end;

procedure buildPath(waypointRefA, waypointRefB: WaypointRef; distance: integer);

  procedure addPath(pRef: PathRef);

    procedure addPathToWaypoint(pRef: PathRef; wRef: WaypointRef);
    var
      lngth: integer;
    begin
      lngth := length(wRef^.pathRefs);
      SetLength(wRef^.pathRefs, lngth + 1);
      wRef^.pathRefs[lngth] := pRef;
    end;

  begin
    addPathToWaypoint(pRef, pRef^.WaypointRefA);
    addPathToWaypoint(pRef, pRef^.WaypointRefB);
  end;

var
  p: path;
begin
  p.distance := distance;
  p.WaypointRefA := waypointRefA;
  p.WaypointRefB := waypointRefB;

  addPath(@p);
end;                      

有两种情况可能会导致这种意外行为:

如果有getter方法支持的航路点[0]和路径参考[0]的数组类型属性:那么这些方法可能会产生副作用,从而导致问题。显然,这里的情况并非如此。 如果您的指针正在引用无效的内存位置:则内存被其他代码覆盖可能会导致值更改。这就是你的问题。 要添加的路径在堆栈上声明:

var
  p: path;  //<-- Stack variable
begin
  ...    
  addPath(@p);
end; //<-- When you leave the method the stack variable is no longer valid.
注意:您必须确定何时何地处置动态分配的内存

EDIT2添加一个简单的控制台应用程序来演示问题

program InvalidUseOfStackVar;

{$APPTYPE CONSOLE}

type
  PData = ^TData;
  TData = record
    Value: Integer;
  end;

var
  GData: PData;

procedure SetData;
var
  LData: TData; //Stack variable will no longer be valid when routine exits.
begin
  LData.Value := 42; //The initial value pointed to by GData
  GData := @LData; //The global var will continue to point to invalid memory after exit.
end;

procedure ChangeStack;
var
  //This is written to have the same stack layout as the previous routine.
  LData: TData;
begin
  LData.Value := 777; //This unintentionally changes data pointed to by the global var
end;

begin
  SetData;                //Sets GData, but GData points to an address on the call stack
  Writeln(GData^.Value);  //Writes 42 because that's what was on the stack at the time of the method call.
  ChangeStack;            //Updates the stack variable to a different value
  Writeln(GData^.Value);  //Now writes 777 because GData points to the same location in memory, but the
                          //data at that location was changed.
  Writeln(GData^.Value);  //Note: calling the Writeln method above also changes the stack.
                          //The only difference is that it is less predictable for us to determine
                          //how the stack will be changed.
  Readln;
end.

有两种情况可能会导致这种意外行为:

如果有getter方法支持的航路点[0]和路径参考[0]的数组类型属性:那么这些方法可能会产生副作用,从而导致问题。显然,这里的情况并非如此。 如果您的指针正在引用无效的内存位置:则内存被其他代码覆盖可能会导致值更改。这就是你的问题。 要添加的路径在堆栈上声明:

var
  p: path;  //<-- Stack variable
begin
  ...    
  addPath(@p);
end; //<-- When you leave the method the stack variable is no longer valid.
注意:您必须确定何时何地处置动态分配的内存

EDIT2添加一个简单的控制台应用程序来演示问题

program InvalidUseOfStackVar;

{$APPTYPE CONSOLE}

type
  PData = ^TData;
  TData = record
    Value: Integer;
  end;

var
  GData: PData;

procedure SetData;
var
  LData: TData; //Stack variable will no longer be valid when routine exits.
begin
  LData.Value := 42; //The initial value pointed to by GData
  GData := @LData; //The global var will continue to point to invalid memory after exit.
end;

procedure ChangeStack;
var
  //This is written to have the same stack layout as the previous routine.
  LData: TData;
begin
  LData.Value := 777; //This unintentionally changes data pointed to by the global var
end;

begin
  SetData;                //Sets GData, but GData points to an address on the call stack
  Writeln(GData^.Value);  //Writes 42 because that's what was on the stack at the time of the method call.
  ChangeStack;            //Updates the stack variable to a different value
  Writeln(GData^.Value);  //Now writes 777 because GData points to the same location in memory, but the
                          //data at that location was changed.
  Writeln(GData^.Value);  //Note: calling the Writeln method above also changes the stack.
                          //The only difference is that it is less predictable for us to determine
                          //how the stack will be changed.
  Readln;
end.

您能否演示如何设置pathRefs数组?如果同时使用数组,为什么要使用指针?请演示完整的测试,以便重现您的问题@不,纽曼,这里有指针,这样记录就可以在不重复的情况下交叉引用数据。@LURD感谢您的快速回复。我添加了创建记录的代码。我想里面一定有错误。@Endzeit:你在哪里创建指针?在您的示例中没有“新的”。您能说明如何设置pathRefs数组吗?如果同时使用数组,为什么要使用指针?请显示完整的测试,以便重现您的问题@不,纽曼,这里有指针,这样记录就可以在不重复的情况下交叉引用数据。@LURD感谢您的快速回复。我添加了创建记录的代码。我想里面一定有错误。@Endzeit:你在哪里创建指针?您的示例中没有“新”的内容。