Решение проблемы инициализации приватных полей в классе Delphi: ошибка с TStringList в Delphi Rio
Разработчики, работающие с Delphi, периодически сталкиваются с различными проблемами, в том числе и с инициализацией приватных полей в пользовательских классах. В данной статье мы рассмотрим типичную проблему, связанную с использованием TStringList в классе, предназначенном для чтения записей из базы данных. Проблема заключается в том, что приватное поле TStringList, инициализированное в конструкторе, становится nil после завершения работы конструктора.
Описание проблемы
В Delphi Rio был создан класс TProfileDef, цель которого - чтение записи из базы данных. Запись предназначена только для чтения, и после её чтения необходимо извлечь дополнительные свойства. Проблема связана с использованием TStringList в определении класса. Существует приватное поле fVENDORS_TO_COLORCODE_SL, которое представляет собой список строк, разделённых запятыми. Разработчик хочет создать свойство, которое будет являться TStringList. В конструкторе создаётся экземпляр TStringList и загружается значение из приватного поля fVENDORS_TO_COLORCODE. Однако, несмотря на то, что TStringList валиден в конструкторе, он становится nil вне его, и разработчик не может понять, в чём заключается ошибка.
Пример кода
type
TProfileDef = class(TObject)
private
fNAME: String;
fVENDORS_TO_COLORCODE: String;
fVENDORS_TO_COLORCODE_SL: TStringList;
// ... другие поля
public
constructor Create(ProfileName: String);
destructor Destroy; override;
published
property NAME: String read fNAME;
property VENDORS_TO_COLORCODE: String read fVENDORS_TO_COLORCODE;
property VENDORS_TO_COLORCODE_SL: TStringList read fVENDORS_TO_COLORCODE_SL;
// ... другие свойства
end;
implementation
destructor TProfileDef.Destroy;
begin
inherited;
fVENDORS_TO_COLORCODE_SL.Free;
end;
constructor TProfileDef.Create(ProfileName: String);
var
lVENDORS_TO_COLORCODE_SL: TStringList;
// ... другие локальные переменные
begin
inherited Create;
fNAME := ProfileName;
// ... логика чтения записи из базы данных
// ...
// Инициализация списка строк
lVENDORS_TO_COLORCODE_SL := TStringList.Create;
lVENDORS_TO_COLORCODE_SL.CommaText := fVENDORS_TO_COLORCODE;
// ... установка ссылки на переменную класса
fVENDORS_TO_COLORCODE_SL := lVENDORS_TO_COLORCODE_SL;
end;
Подтвержденный ответ
Проблема заключается в том, что в конструкторе класса TProfileDef существует локальная переменная lVENDORS_TO_COLORCODE_SL, которая перезаписывает приватное поле fVENDORS_TO_COLORCODE_SL класса. Это приводит к тому, что после завершения работы конструктора, при попытке доступа к свойству VENDORS_TO_COLORCODE_SL объекта класса TProfileDef происходит доступ к неинициализированной памяти, что вызывает ошибку выполнения программы (access violation).
Решение проблемы
Для решения проблемы необходимо убрать локальную переменную lVENDORS_TO_COLORCODE_SL в конструкторе и напрямую инициализировать приватное поле класса:
constructor TProfileDef.Create(ProfileName: String);
begin
inherited Create;
fNAME := ProfileName;
// ... логика чтения записи из базы данных
// ...
// Инициализация приватного поля класса
fVENDORS_TO_COLORCODE_SL := TStringList.Create;
fVENDORS_TO_COLORCODE_SL.CommaText := fVENDORS_TO_COLORCODE;
end;
Также стоит убедиться, что деструктор класса корректно освобождает выделенные ресурсы:
destructor TProfileDef.Destroy;
begin
if Assigned(fVENDORS_TO_COLORCODE_SL) then
fVENDORS_TO_COLORCODE_SL.Free;
inherited;
end;
Заключение
При работе с приватными полями классов в Delphi важно следить за тем, чтобы не перезаписывать их локальными переменными в конструкторе. Кроме того, необходимо убедиться, что деструктор класса корректно освобождает ресурсы, выделенные для приватных полей. Следуя этим рекомендациям, можно избежать типичных ошибок, связанных с инициализацией и освобождением памяти в пользовательских классах.
Разработчики столкнулись с ошибкой в Delphi Rio, связанной с инициализацией и управлением памятью приватного поля `TStringList` в классе `TProfileDef`, используемом для работы с данными из базы данных.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.