Không, tôi không nghĩ một điều như vậy có thể xảy ra. Có thể cho một biến chuỗi để có được một giá trị mà bạn không mong đợi, nhưng nó sẽ không bị rò rỉ bộ nhớ. Hãy xem xét điều này:
var
Global: string;
procedure One(const Arg: string);
begin
Global := '';
// Oops. This is an invalid reference now. Arg points to
// what Global used to refer to, which isn't there anymore.
writeln(Arg);
end;
procedure Two;
begin
Global := 'foo';
UniqueString(Global);
One(Global);
Assert(Global = 'foo', 'Uh-oh. The argument isn''t really const?');
end;
Đây là đối số được tuyên bố là const, vì vậy được cho là sẽ không thay đổi. Nhưng sau đó One
circumvents rằng bằng cách thay đổi các tham số thực tế thay vì tham số chính thức. Thủ tục Two
"biết" rằng đối số của One
là const, do đó, nó hy vọng tham số thực tế để giữ lại giá trị ban đầu của nó. Xác nhận không thành công.
Chuỗi không bị rò rỉ, nhưng mã này không cho biết cách bạn có thể nhận được một tham chiếu dang lửng cho một chuỗi. Arg
là bí danh địa phương của Global
. Mặc dù chúng tôi đã thay đổi Global
, giá trị của Arg
vẫn không bị ảnh hưởng và bởi vì nó được khai báo const, số lượng tham chiếu của chuỗi không tăng lên khi nhập vào hàm. Chỉ định lại Global
đã giảm số tham chiếu về 0 và chuỗi đã bị hủy. Khai báo Arg
vì var sẽ có cùng một vấn đề; chuyển nó theo giá trị sẽ khắc phục vấn đề này. (Gọi tới UniqueString
chỉ để đảm bảo chuỗi được tính tham chiếu. Nếu không, nó có thể là một chuỗi ký tự không được tham chiếu.) Tất cả các loại do trình biên dịch quản lý đều dễ bị vấn đề này; loại đơn giản là miễn dịch.
Cách duy nhất để làm rò rỉ chuỗi là xử lý nó dưới dạng chuỗi khác, hoặc sử dụng các chức năng quản lý bộ nhớ không nhận dạng.Mghie's answer mô tả cách xử lý chuỗi dưới dạng chuỗi khác bằng cách sử dụng FillChar
để nén một biến chuỗi. Các chức năng bộ nhớ không nhận dạng bao gồm GetMem
và FreeMem
. Ví dụ:
type
PRec = ^TRec;
TRec = record
field: string;
end;
var
Rec: PRec;
begin
GetMem(Rec, SizeOf(Rec^));
// Oops. Rec^ is uninitialized. This assignment isn't safe.
Rec^.field := IntToStr(4);
// Even if the assignment were OK, FreeMem would leak the string.
FreeMem(Rec);
end;
Có hai cách để khắc phục. Một là để gọi Initialize
và Finalize
:
GetMem(Rec, SizeOf(Rec^));
Initialize(Rec^);
Rec^.field := IntToStr(4);
Finalize(Rec^);
FreeMem(Rec);
Các khác là sử dụng chức năng loại-aware:
New(Rec);
Rec^.field := IntToStr(4);
Dispose(Rec);
Điều đó có vẻ giống như tôi đang nghĩ, nhưng nó không phải AV trong năm 2009, mà tôi tin là những gì bạn đang nói. –
Nó không AV vì trong Delphi 2009, "const" mất chức năng của nó nếu $ STRINGCHECKS được BẬT. –