Исправление ошибки локальных переменных в функции сравнения CustomSort для 64-битной версии Delphi XE3
В статье рассматривается проблема, связанная с использованием локальных функций в методе CustomSort компонента TStringList в среде Delphi XE3 при компиляции в 64-битном режиме. Проблема заключается в возникновении ошибки доступа к памяти при попытке передачи адреса локальной функции в качестве параметра для сортировки. Обсуждается, почему такой код работает в 32-битной версии, но приводит к ошибкам в 64-битной, и предлагается решение проблемы.
Описание проблемы
Пользователь столкнулся с проблемой, при которой локальная функция сравнения, используемая в методе CustomSort компонента TStringList, работает корректно при компиляции под 32-битную версию Delphi XE3, но вызывает ошибку доступа к памяти при использовании 64-битной версии. В 64-битной версии функция сравнения получает nil в качестве параметра s, что указывает на проблему с передачей адреса локальной функции.
Пример кода, вызывающего ошибку
procedure TForm2.btn1Click(Sender: TObject);
var
s: TStringList;
function compare(const S: TStringList; i1, i2: Integer): Integer;
begin
Result := CompareText(S[i1], S[i2]);
end;
begin
s := TStringList.Create;
try
s.Add('s1');
s.Add('s2');
s.Add('s3');
s.CustomSort(@compare);
finally
s.Free;
end;
end;
Этот код работает корректно в 32-битной версии, но вызывает ошибку доступа в 64-битной. Если функция сравнения определена вне функции btn1Click, то ошибка не возникает.
Подтвержденный ответ
Проблема заключается в том, что локальные функции не должны передаваться по ссылке в качестве параметров для других функций. Это связано с тем, что локальные функции должны иметь доступ к стеку своих родительских функций, который не существует, если они вызываются напрямую без предшествующего вызова родительских функций. В документации Embarcadero по этому вопросу можно найти более подробную информацию.
Исправление заключается в том, чтобы сделать функцию сравнения глобальной, чтобы она могла быть вызвана без проблем с доступом к стеку.
Пример исправленного кода
function compare(const S: TStringList; i1, i2: Integer): Integer;
begin
Result := CompareText(S[i1], S[i2]);
end;
procedure TForm2.btn1Click(Sender: TObject);
var
s: TStringList;
begin
s := TStringList.Create;
try
s.Add('s1');
s.Add('s2');
s.Add('s3');
s.CustomSort(@compare);
finally
s.Free;
end;
end;
Теперь функция compare определена вне функции btn1Click, что позволяет ей корректно работать в 64-битной версии Delphi XE3.
Заключение
При работе с локальными функциями в среде Delphi важно помнить о правилах их использования и передачи в качестве параметров. В случае с 64-битной версией Delphi XE3, необходимо избегать передачи адреса локальной функции, что может привести к ошибкам доступа к памяти. Использование глобальных функций является правильным подходом для обеспечения корректной работы с компонентами, такими как TStringList и его методом CustomSort.
Проблема заключается в некорректной передаче адреса локальной функции для сортировки в компоненте `TStringList` при компиляции в 64-битной версии Delphi XE3, что требует изменения функции сравнения на глобальную для исправления ошибки.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.