4

こんな記録を残しています

  TEmf_SrectchDIBits = packed record
    rEMF_STRETCHDI_BITS: TEMRStretchDIBits;
    rBitmapInfo: TBitmapInfo;
    ImageSource: string;
  end;
  ---
  ---
  RecordData: TEmf_SrectchDIBits;

このように TStream を使用してデータを読み込んでいると、例外が発生します

SetLength(RecordData.ImageSource, pRecordSize);

EMFStream.ReadBuffer(RecordData.ImageSource,pRecordSize) 

しかし、以下のコードを使用すると、正常に動作していました

SetLength(RecordData.ImageSource, pRecordSize);

EMFStream.ReadBuffer(RecordData.ImageSource[1], pRecordSize);

では、String と String[1] の使用の違いは何ですか?

4

2 に答える 2

12

違いは、.ReadBuffer メソッドの署名に関連する詳細です。

署名は次のとおりです。

procedure ReadBuffer(var Buffer; Count: Longint);

ご覧のとおり、Buffer パラメータには型がありません。この場合、基になる変数にアクセスする必要があると言っています。

ただし、文字列は、ポインター (変数の内容) と文字列 (変数がこれを指す) の 2 つの部分で構成されます。

そのため、ReadBuffer に文字列変数だけが与えられた場合、文字列変数にデータを格納するための 4 バイトが必要になり、文字列変数はランダムなバイナリ データだけでなくポインターを保持することになっているため、うまくいきません。 . ReadBuffer が 4 バイトを超える書き込みを行った場合、メモリ内の別のデータが新しいデータで上書きされ、悲惨な結果を招く可能性があります。

[1] 文字をvarパラメーターに渡すことで、必要な文字列変数が指すデータへの ReadBuffer アクセスを許可します。結局、文字列の内容を変更したい。

また、文字列変数の長さを、読み込んでいるものを保持するのに十分な大きさに設定したことを確認してください。

また、最後に、私が確認できないものです。Delphi の古いバージョンでは、文字列変数に 1 バイト文字が含まれていました。新しいバージョンでは、Unicode のために 2 つだと思うので、新しいバージョンの Delphi ではコードが期待どおりに機能しない可能性があります。代わりに、バイト配列またはヒープ メモリを使用することをお勧めします。

于 2010-07-07T07:49:48.173 に答える
5

文字列型は、実際には「文字列記述子ブロック」と呼ばれるものへのポインタとして実装されます。基本的に、ある程度の間接性があります。そのブロックには、負のオフセットでいくつかの文字列制御データ (参照カウント、長さ、およびそれ以降のバージョンでは文字セット情報も) が含まれ、正のオフセットで文字列文字が含まれます。文字列変数は、記述ブロックへのポインターです (そして、SizeOf(stringvar) を出力すると 4 になります)。文字列を処理するとき、コンパイラーは文字列データを見つけて処理する場所を認識しますただし、型指定されていないパラメーター (var Buffer;) を使用する場合、コンパイラーはそれを認識せず、単に「バッファー」のメモリにアクセスしますが、ポインターである文字列変数を使用します。実際の文字列文字ではなく、文字列ブロックに。string[1] を使用して、最初の文字データの位置を渡します。

于 2010-07-07T08:48:19.343 に答える