0

在 VirtualTreeview 中,我将数据存储在PVirtualNodes中。我在我的应用程序中经历了几次访问冲突(通常是"Read of adress 00000000"),它们大多(我实际上敢说总是)发生在我对节点数据做某事时。

然而,问题是,我声明我的东西并像这样使用它:

// DUMMY CODE - Not written or tested in IDE
var
 MyNode : PVirtualNode;
 MyData : PMyNodeData;
Begin
 MyNode := VST.GetFirstSelected;

 if Assigned(MyNode) then
  Begin
   MyData := VST.GetNodeData(MyNode);
   if Assigned(MyData) then
   Begin
     MyData.DummyProperty := 'Test';
   End;
  End;
End;

您可能已经注意到,我不会通过执行MyData^来“取消引用”(正确的?)我的“MyData”!我不这样做的原因是有人告诉我没有必要将插入符号添加到指针名称中,但是我感觉它与它有关。如果我知道,我不会在这里发帖。;)

所以我的问题是:最终是否有必要将一点点添加^到 MyData 中?如果不这样做,我是否有可能引发访问冲突?

4

3 回答 3

4

当你有一个指向记录的指针时,你可以省略 ^。以下是等价的:

MyData.DummyProperty
MyData^.DummyProperty

已弃用的 Turbo Pascal 也是如此object。我希望 Delphi 类会如此,尽管我从未尝试过它们,因为它们已经是引用类型。

可悲的是,这不是您的 AV 的解释。

于 2011-03-28T16:36:02.143 回答
2

使用 ^ 取消引用记录是可选的,因为它是由编译器隐式假定的。当不使用任何硬类型转换时,任何需要“^”的情况都不会编译。但只有 1 级取消引用是隐式的。

type
  TMyRecord  = record
    MyField : Integer;
  end;
  PMyRecord = ^TMyRecord;
  PPMyRecord = ^PMyRecord;

procedure DoSomething;
var vMyField : PPMyRecord;
begin
  vMyField.MyField;  <---Won't compile
  vMyField^.MyField; <---Will compile
end;

至于您的访问违规,这是我根据您所写内容的最佳猜测...假设您的示例具有代表性(即,分配字符串时崩溃),并假设 PMyNodeData 指向记录。我猜 PMyNodeData 的内存是用“GetMem”而不是“New”保留的,这使得记录的字符串字段未初始化。

于 2011-03-28T17:18:59.307 回答
1

有一个例外 where Data.xxandData^.xx不一样:当指向的字段是相同的指针类型或泛型指针类型时:

var
  x: PPointer;
  y: Pointer;
begin
  x := GetPPointer();
  y := x;
  y := x^;
end;

我认为最好的做法是^在使用指向值时始终添加运算符以避免上述模棱两可的情况。

鉴于您的示例:问题可能是内存损坏。你设置NodeDataSize正确了吗?

于 2011-03-29T06:48:05.103 回答