0

VirtualTreeviewでは、データをPVirtualNodesに保存しています。私は自分のアプリでいくつかのアクセス違反(通常は「Readof adress 00000000」 )を経験しましたが、ノードデータで何かをしているときにほとんど(実際には「Always」と言ってもいいでしょう)発生します。

ただし、問題は、自分のものを宣言して、次のように使用することです。

// 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

これは、非推奨のTurboPascalにも当てはまりobjectます。Delphiクラスはすでに参照型であるため、試したことはありませんが、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のメモリは、「New」ではなく「GetMem」で予約されていたため、レコードの文字列フィールドが初期化されていなかったと思います。

于 2011-03-28T17:18:59.307 に答える
1

とが同じでない場合の例外がありData.xxます。Data^.xxポイントされたフィールドが同じポインタ型またはジェネリックポインタ型である場合:

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

^上記のようなあいまいな状況を回避するために、指定された値を使用する場合は、常に演算子を追加することがベストプラクティスだと思います。

あなたの例を考えると:問題はおそらくメモリの破損です。NodeDataSize正しく設定しましたか?

于 2011-03-29T06:48:05.103 に答える