Только мои два цента. Ответ Тендрея правильный, но я просто хотел подчеркнуть некоторые моменты. И комментарии не являются хорошим местом для этого.
Обратите внимание, что на AnsiString
должна быть ссылка в течение всего времени TVarRec
.
Например, если вы пишете функцию, устанавливающую массив TVarRec
, вы должны убедиться, что вы сделали временную копию AnsiString
, созданную в функции, в переменную, которая будет оставаться до тех пор, пока TVarRec
массив используется. В противном случае у вас может возникнуть какое-либо нарушение произвольного доступа (не каждый раз, а только в том случае, если ММ переназначит память 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)
подобными утверждениями, могут быть сложными для отслеживания.