0

さて、長くなります!

私が取り組んでいるLANシミュレーションプロトコルのために、ドロップされたUDPパケットを管理するための再送信スキームを作成しました。

パケット ストレージ

TDataBuffer = record

  PacketID : WORD;
  Packet   : TMemoryStream;

end;
PDataBuffer = ^TDataBuffer;

関連する DataModule クラス メンバー

fRxDataPacketList  : TThreadList20;
fTxDataPacketList  : TThreadList20;

procedure CreateDataBuffer
          (PacketID : WORD; Packet : TMemoryStream;
           var DataBuffer : PDataBuffer);

procedure DestroyDataBuffer
          (var DataBuffer : PDataBuffer);

procedure AddPacketToPacketList
          (PacketID : WORD; Packet : TMemoryStream;
           RecievedPacket : Boolean);

function  GetPacketFromTxDataPacketList
          (PacketID : WORD; var Packet : TMemoryStream): Boolean;

TThreadList20: これは、スレッド フレンドリーで、暗号化と圧縮をサポートする TList のラッパー クラスです。

私の質問に関係のないRx側を処理するための別の手順があるので、スキップします。

創造

procedure TDataModuleClient.CreateDataBuffer
          (PacketID : WORD; Packet : TMemoryStream; 
           var DataBuffer : PDataBuffer);

begin

  New (DataBuffer);
  DataBuffer.PacketID := PacketID;
  DataBuffer.Packet   := TMemoryStream.Create;

  if Assigned (Packet) then 
  begin

    DataBuffer.Packet.CopyFrom (Packet,Packet.Size); // NO AV HERE
    DataBuffer.Packet.Position := 0;

  end;

end;

破壊

procedure TDataModuleClient.DestroyDataBuffer
          (var DataBuffer : PDataBuffer);
begin

  DataBuffer.Packet.Free;
  Dispose (DataBuffer);

end;

リストへの追加

procedure TDataModuleClient.AddPacketToDataPacketList
          (PacketID : WORD; Packet : TMemoryStream; RecievedPacket : Boolean);
var
  DataBuffer : PDataBuffer;

begin

  CreateDataBuffer (PacketID,Packet,DataBuffer);

  if RecievedPacket then
    fRxDataPacketList.Add (TObject (DataBuffer))

  else
  begin

    fTxDataPacketList.Lock;

    try

      fTxDataPacketList.Add (TObject (DataBuffer));

      if fRxDataPacketList.Count = 21 then
      begin

        DataBuffer := PDataBuffer (fTxDataPacketList [0]);

        DestroyDataBuffer (DataBuffer);
        fTxDataPacketList.Delete (0);

      end;

    finally fTxDataPacketList.Unlock;
    end;

  end;

end;

リストからの抽出

function  TDataModuleClient.GetPacketFromTxDataPacketList
          (PacketID : WORD; var Packet : TMemoryStream): Boolean;
var
  DataBuffer : PDataBuffer;
  I          : Integer;

begin

  Result := False;
  fTxDataPacketList.Lock;

  try

    for I := fTxDataPacketList.Count - 1 downto 0 do
    begin

      DataBuffer := PDataBuffer (fTxDataPacketList [I]);

      if DataBuffer.PacketID < PacketID then
      begin

        DestroyDataBuffer (DataBuffer);
        fTxDataPacketList.Delete (I);

      end
      else if DataBuffer.PacketID = PacketID then
      begin

        Result := True;

        Packet := TMemoryStream.Create;

        Packet.CopyFrom
        (DataBuffer.Packet,DataBuffer.Packet.Size); // AV HERE
        Packet.Position := 0;

        DestroyDataBuffer (DataBuffer);
        fTxDataPacketList.Delete (I);

        break;

      end;

    end;

  finally fTxDataPacketList.Unlock;
  end;

end;

パケット: 出力変数。

助けてください。コードの量のおかげで、何かを推測するのは難しいように見えます。

4

1 に答える 1

2

この限られたコードに基づいて、いくつかの推測を行っています。

1)Packetに渡される入力は、GetPacketFromTxDataPacketList()実際にはまだインスタンス化されていない可能性がありますCopyFrom()。それはAVの説明になります。

2)Packetパラメータは として宣言されているため、呼び出し元が を作成してデータで埋めるのではなく、作成して返すことになってvarいる出力パラメータであることを示唆しています。新しいオブジェクトを作成するのではなく、オブジェクトが事前に作成されていると想定しているため、これも#1に影響します。GetPacketFromTxDataPacketList()TMemoryStreamGetPacketFromTxDataPacketList()GetPacketFromTxDataPacketList()TMemoryStream

于 2012-11-08T18:56:35.160 に答える