長期以來,我錯誤地認為 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;
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+左鍵)是驗證假設的唯一可靠途徑。