只是我的两分钱。TOndrej 的回答是正确的,但我只是想强调几点。评论不是一个好地方。
请注意,AnsiString
在所有时间都必须引用的TVarRec
将被使用。
例如,如果您编写一个设置数组的函数TVarRec
,您应该确保AnsiString
将函数中创建的临时副本复制到一个变量,该变量将一直保留到该TVarRec
数组被使用为止。否则你可能会遇到一些随机访问冲突(不是每次,但只有当 MM 重新分配ansistring
内存时)。
例如,以下代码不正确:
type
TVarRec2 = array[0..1] of TVarRec;
procedure SetVarRec(a,b: integer; var Result: TVarRec2);
begin
Result[0].VType := vtAnsiString;
Result[0].VString := pointer(AnsiString(IntToStr(a)));
Result[1].VType := vtUnicodeString;
Result[1].VString := pointer(UnicodeString(IntToStr(b)));
end;
因为AnsiString
和UnicodeString
临时变量将在过程结束时被释放,并且Results[].VString
仍然指向那些释放的内存......
使用带有一些临时私有字符串的类或记录可以解决问题:
type
TMyVar2 = record
private
tmpA: AnsiString;
tmpB: UnicodeString;
public
VarRec: TVarRec2;
procedure SetVarRec(a,b: integer);
end;
procedure TMyVar2.SetVarRec(a,b: integer);
begin
VarRec[0].VType := vtAnsiString;
tmpA := AnsiString(IntToStr(a));
VarRec[0].VString := pointer(tmpA);
VarRec[1].VType := vtUnicodeString;
tmpB := UnicodeString(IntToStr(b));
VarRec[1].VString := pointer(tmpB);
end;
当然,在您的程序中,您可能已经有一个类。在这种情况下,您最好使用方法和一些私有临时字符串。对于多线程安全的方法(即可重入),您应该提供临时字符串作为参数...
我使用这个技巧来获得一个TVarData
包含类中某些AnsiString
内容的有效动态数组。事实上,TVarData
两者 TVarRec
都使用这种指向字符串的非引用指针,这可能会造成混淆。
请注意,涉及pointer(S)
类似语句的问题可能难以跟踪。