Delphi 提供十幾個內存分配函數,但針對字符指針 (PChar、PWideChar、PAnsiChar),StrAlloc 是專門設計、最安全、最高效的選擇。本文深度解析其原理與相關函數族。
GetMem AllocMem ReallocMem FreeMem
GetMemory ReallocMemory FreeMemory
New Dispose
NewStr DisposeStr
StrNew StrAlloc StrDispose StrBufSize
GlobalAllocPtr GlobalFreePtr
WideStrAlloc AnsiStrAlloc
Move MoveMemory CopyMemory
ZeroMemory FillMemory StrBufSize
StrDispose 釋放,StrBufSize 獲取大小PWideChar 調用 WideStrAlloc,PAnsiChar 調用 AnsiStrAlloc#0 結尾,帶長度前綴var
p: PChar;
begin
p := StrAlloc(256); // 分配 256 字符 (含管理頭)
try
GetWindowText(Handle, p, StrBufSize(p)); // 獲取標題
ShowMessage(p); // 顯示
finally
StrDispose(p); // 正確釋放 (含管理頭)
end;
end;
為什麼不用 FreeMem? 會少釋放 4 字節管理頭,導致內存洩漏。
var
buf: array[0..MAX_PATH] of Char;
begin
GetWindowsDirectory(buf, Length(buf));
ShowMessage(buf); // C:\Windows
end;
MAX_PATH=260)var p: PChar;
begin
p := '萬一的 Delphi 博客'; // 編譯器生成常量段數據
ShowMessage(p); // 直接使用,無需分配/釋放
end;
var p: PChar;
begin
p := PChar(StringOfChar(#0, 256)); // 256 個 #0
GetSystemDirectory(p, StrBufSize(p));
ShowMessage(p); // C:\Windows\system32
end;
// 直接常量
SetWindowText(Handle, '新標題');
// 變量轉型
var str: string;
begin
str := '萬一的 Delphi 博客';
TextOut(Canvas.Handle, 10, 10, PChar(str), Length(str));
end;
| 函數 | 用途 | 備註 |
|---|---|---|
StrAlloc | 分配字符串緩衝區 (含管理頭) | 首選,自動識別寬/窄字符 |
WideStrAlloc | 顯式分配寬字符緩衝區 | StrAlloc(PWideChar) 內部調用 |
AnsiStrAlloc | 顯式分配 ANSI 字符緩衝區 | StrAlloc(PAnsiChar) 內部調用 |
StrDispose | 釋放 StrAlloc 分配的內存 | 必須配對使用 |
StrBufSize | 獲取緩衝區可用大小 (扣除管理頭) | 傳給 API 的長度參數 |
StrNew | 複製字符指針 (分配新內存) | 少用,直接賦值 p2 := p1 共享更簡單 |
NewStr/DisposeStr | 已棄用 (deprecated) | 兼容舊代碼,用 @str 獲取指針 |