Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Почему сравнение указателя на функцию с nil вызывает ошибку E2008 в Delphi?

Delphi , Синтаксис , Память и Указатели

Проблема, с которой сталкиваются разработчики, использующие Delphi, заключается в некорректном сравнении указателя на функцию с nil. В коде, предоставленном Anders Melander для его набора Drag Drop, используется следующий фрагмент в модуле DragDrop.pas:

var
  URLMONDLL: THandle = 0;
  _CopyStgMedium: function(const cstgmedSrc: TStgMedium; var stgmedDest: TStgMedium): HResult; stdcall = nil;
...
function CopyStgMedium(const SrcMedium: TStgMedium; var DstMedium: TStgMedium): boolean;
begin
  // ...
  if (URLMONDLL = 0) then
  begin
    URLMONDLL := LoadLibrary('URLMON.DLL');
    if (URLMONDLL <> 0) then
      @_CopyStgMedium := GetProcAddress(URLMONDLL, 'CopyStgMedium');
  end;

  if (@_CopyStgMedium = nil) then // E2008 Incompatible types
    raise Exception.Create(sNoCopyStgMedium);
  // ...
end;

Компиляция проходит для следующих вариантов проверки:

if (@@_CopyStgMedium = nil) then // Логическая ошибка, это указатель на процедурную переменную
if (Pointer(@_CopyStgMedium) = nil) then // Правильно
if not(Assigned(@_CopyStgMedium)) then // Правильно

Однако, при попытке сравнения @_CopyStgMedium с nil возникает ошибка E2008, указывающая на несовместимость типов. Это происходит даже несмотря на то, что оператор @ установлен в режим типизированных указателей ({$T+}).

Подтвержденный ответ заключается в том, что использование оператора @ в данном контексте является излишним и вводит в заблуждение. Правильный способ написания кода:

function CopyStgMedium(const SrcMedium: TStgMedium; var DstMedium: TStgMedium): boolean;
begin
  // ...
  if (URLMONDLL = 0) then
  begin
    URLMONDLL := LoadLibrary('URLMON.DLL');
    if (URLMONDLL <> 0) then
      _CopyStgMedium := GetProcAddress(URLMONDLL, 'CopyStgMedium');
  end;

  if not Assigned(_CopyStgMedium) then
    raise Exception.Create(sNoCopyStgMedium);
  // ...
end;

Оператор @ используется для разрешения неоднозначности между вызовом функции и обращением к ней. Следовательно, сравнение _CopyStgMedium = nil некорректно, так как это попытка вызвать функцию. В то же время, на первый взгляд, @_CopyStgMedium = nil должно работать, но из-за типизации указателей, @_CopyStgMedium является типизированным указателем на функцию и не может быть сравнен с nil. Возможен приведение типа с помощью Pointer(@_CopyStgMedium), но предпочтительнее использовать Assigned.

Документация утверждает, что @ при обращении к процедурной переменной возвращает нетипизированный указатель, но при включенной типизации адресов ({$T+}) это не так. В более старых версиях, например, в XE3, @ возвращает нетипизированный указатель даже с включенной типизацией адресов. Возможно, документация не соответствует действительности, и это является ошибкой компилятора. Рекомендуется подать сообщение об ошибке.

Альтернативный ответ заключается в том, что использование @ с процедурными переменными приводит к созданию типизированного указателя на процедуру, который несовместим с nil. Для исправления ситуации можно явно привести тип к Pointer, но более правильным решением является использование функции Assigned.

В заключение, для избежания подобных проблем рекомендуется не использовать оператор @ с процедурными переменными и отдавать предпочтение функции Assigned для проверки на присвоение значения.

Создано по материалам из источника по ссылке.

Разработчики Delphi сталкиваются с ошибкой E2008 при попытке сравнения указателя на функцию с nil из-за неправильного использования оператора @ и недопонимания типов в языке программирования.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Память и Указатели ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-08-30 17:09:34/0.0053658485412598/1