首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

Delphi 記憶體流陷阱:TMemoryStream.Memory 指標不隨 Position 變化

     編輯:Delphi

長期以來,我錯誤地認為 TMemoryStream 的 Position 屬性改變時,其 Memory 指標也會跟著移動。這純粹是「想當然」的後果——沒有深入原始碼驗證過。

錯誤認知的實測程式碼

procedure TForm1.FormCreate(Sender: TObject); 
var 
  Stream1, Stream2: TMemoryStream; 
  pw: TPtrWrapper; 
begin 
  Stream1 := TStringStream.Create('1234567890'); 
  Stream2 := TStringStream.Create('ABCDEFGHIJ'); 
  
  // 嘗試將 Stream1 修改為 '123DEFG890'
  // 錯誤假設:Stream1.Position := 3 後,Stream1.Memory 會指向第 4 個字元
  pw := TPtrWrapper.Create(Stream2.Memory); 
  pw := TPtrWrapper.Create(pw.ToInteger + 3); // 取 Stream2 記憶體偏移 +3 位置
  
  Stream1.Position := 3; // 移動到第 4 個字元位置
  Stream1.Write(pw.ToPointer^, 4); // 寫入 4 個字元
  
  ShowMessage(TStringStream(Stream1).DataString); // 實際輸出: 123DEFG890
  
  Stream1.Free; 
  Stream2.Free; 
end;

核心真相

  • TMemoryStream.Memory 永遠指向緩衝區起始位址,不會隨 Position 改變而移動
  • Position 僅影響 讀寫操作的邏輯位置,底層指標保持不變
  • 上述程式碼之所以「看似成功」,是因為 TStringStream 繼承自 TMemoryStream,且 Write 方法內部正確處理了 Position 偏移

正確操作模式

若需根據 Position 進行指標運算,應手動計算偏移:

var
  BasePtr: Pointer;
  OffsetPtr: Pointer;
begin
  BasePtr := Stream1.Memory;           // 取得緩衝區基址
  OffsetPtr := Pointer(NativeUInt(BasePtr) + Stream1.Position); // 手動計算實際位址
  // 使用 OffsetPtr 進行記憶體操作
end;

教訓:永遠不要對框架行為「想當然」,閱讀原始碼(Ctrl+左鍵)是驗證假設的唯一可靠途徑。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved