1

プロシージャへの var またはポインタとして tmemorystream を渡そうとすると、壊れて返されます。これを行う適切な方法は何ですか?

例えば:

function tform1.downloadmemupdate(url, desc: string; var data: tmemorystream; var msg: string): boolean;
begin
  filelabel.Caption:=desc;
  downloadmemthread:=tdownloadmemthread.create(url);
  dlcancelbtn.Enabled:=true;
  downloadmemthread.dlstart;
  waitforsingleobject(downloadmemthread.Handle, INFINITE);

  downloadmemthread.data.SaveToStream(data); //corrupted
  downloadmemthread.data.SaveToFile('data.zip');  //works

  dlcancelbtn.Enabled:=false;
  result:=not (downloadmemthread.canceled and downloadmemthread.success);
  dlcanceled:=downloadmemthread.canceled;
  msg:=downloadmemthread.msg;
  downloadthread.Free;
end;
4

1 に答える 1

5

dataこのメソッド内では作成しません。これは var (byref) パラメータであるため、次のように作成されると予想されます tform1.downloadmemupdate

data := TMemoryStream.Create;

このようなオブジェクトを作成する場合は、別の場所 (おそらく呼び出し元のコード) で解放する必要があることに注意してください。

例えば

   Data := nil;
   try
     downloadmemupdate(url, desc, data, msg);
     // do something with data
   finally
     Data.Free;
   end;  

別の方法(および Delphi の慣用的な方法)は、オブジェクトを値で(var なしで)渡すことです。呼び出し元のコードに任せて、それらを作成および破棄します。これは主に、Delphi にはガベージ コレクションがないためです。そのため、呼び出し元のコードを書く人は「所有権」について考える必要があります。

これは

function tform1.downloadmemupdate(url, desc: string; data: TStream; var msg: string): boolean;
begin
  filelabel.Caption:=desc;
  downloadmemthread:=tdownloadmemthread.create(url);
  try
    ...
    downloadmemthread.data.SaveToStream(data); //corrupted
    downloadmemthread.data.SaveToFile('data.zip');  //works    
  finally
    downloadmemthread.Free;
  end;

end;

呼び出しコード:

   Data := TMemoryStream.Create;
   try
     downloadmemupdate(url, desc, data, msg);
     // do something with data
   finally
     Data.Free;
   end;  
于 2012-11-06T05:43:11.583 に答える