TMemoryStreamのMemoryプロパティ使用について質問します

解決


jiro  2021-08-21 14:20:07  No: 149817

簡素化したコードを作ってみたのですが下記コードでもエラーが出ます。
古いバージョンでは可能だったように思ったのですがうまくいきません。access violationです。
良い方法はないでしょうか。

program Project1;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils,
  System.Classes;

var
  ms: TMemoryStream;
  i: integer;
  a: ^TArray<integer>;

begin
  try
    { TODO -oUser -cConsole メイン : ここにコードを記述してください }
    ms := TMemoryStream.Create;
    i := 7;
    ms.WriteData(i);
    i := 3;
    ms.WriteData(i);
    a := ms.Memory;
    Writeln('start');
    for i := 0 to ms.Size div SizeOf(Integer) do
      Writeln(a^[i]);
    Readln;
    ms.Free;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;

end.


Mr.XRAY  2021-08-22 09:53:43  No: 149818

TArray<T> は動的配列の型です.
SetLength で領域 (要素数) の確保が必要です.

要素が 2 つの時は 0, 1 までです.

    for i := 0 to ms.Size div SizeOf(Integer) do 
      ↓
    for i := 0 to ms.Size div SizeOf(Integer) - 1 do 
  
  
>    a := ms.Memory;

動的配列に対してこのような操作はできません.
TMemoryStream のデータを動的配列に読み込ませたいのあれば,
TMemoryStream.Read メソッドを使用します.

    // a の変数の型は TArray<Integer> (^ はなし)
    SetLength(a,2);
    ms.Position := 0;
    ms.Read(a[0], SizeOf(Integer) * Length(a));


jiro  2021-08-23 13:23:33  No: 149820

よくわかりました。ありがとうございました。


Mr.XRAY  2021-08-23 16:01:33  No: 149821

>>    a := ms.Memory;
    
やるならば,

    Pointer(a) := ms.Memory;
    
ですね.    
ただし,これは TMemoryStream のデータを配列に読み込むのではなく,
TMemoryStream のデータのアドレスと配列のデータのアドレスを同じにする操作です.
ポインタに関する操作ですから,いろいろ注意が必要です.

    Pointer(a) := ms.Memory;

    ms.Position := Sizeof(Integer);
    i := 12345;
    ms.WriteData(i);
    //  a[1] の値は 12345 になる
    
    a[0] := 5005;
    ms.Position := 0;
    ms.ReadData(i);
    // i の値は 5005 になる


※返信する前に利用規約をご確認ください。








  このエントリーをはてなブックマークに追加