Является ли это ошибкой, которая пытается скомпилировать этот код, приводит к завершению IDE или компилятору, который не может работать?

Остерегайтесь использования команды Exit в встроенных функциях! Я использую Delphi XE3 здесь.

Симптом

При определенных обстоятельствах, когда вызов выполняется встроенной функцией, содержащей команду Exit, а возвращаемое значение встроенной функции используется непосредственно в WriteLn(), компилятор сообщает об ошибке,

"dcc" вышел с кодом 1.

или даже хуже, среда ID Delphi завершается без какого-либо подтверждения.

function ProcessNumber(const iNumber: Integer): Boolean; inline;
begin
  if iNumber = 0 then begin
    Result := False;
    Exit;
  end;
  // some code here ...
  Result := True;
end;

procedure Test;
begin
  writeln( ProcessNumber(0) );
end;

begin
  Test;
  ReadLn;
end.

Однако, если возвращаемое значение встроенной функции сохраняется в переменной, а затем переменная используется в WriteLn(), проблема не возникает.

procedure Test;
var
  b: Boolean;
begin
  b := ProcessNumber(0);
  writeln(b);
end;

Вопросы

  • Является ли это ошибкой компилятора?
  • Если это ошибка, есть ли временное решение для безопасного выхода из встроенной функции?

Ответ 1

Это, безусловно, ошибка. Это происходит во всех версиях IDE, которые я тестировал, XE3, XE7 и XE8. Я, честно говоря, не думаю, что вы можете многое сделать. Для меня среда IDE заканчивается при компиляции каждый раз. Я думаю, вам просто нужно написать код таким образом, чтобы не приводить к сбоям IDE.

Вы можете использовать параметр IDE, который заставляет компиляцию использовать msbuild. Это ставит компиляцию в отдельный процесс и поэтому гарантирует, что среда IDE не будет аварийно завершена. Это не поможет вам, хотя, хотя ваша среда разработки не будет продолжать умирать, вы все равно не сможете скомпилировать свою программу!

Когда вы создаете с помощью msbuild, вы получаете ошибку этой формы:

ошибка F2084: Внутренняя ошибка: GPFC00000FD-004D3F34-0

GPF означает "Обнаружение общей защиты", то есть нарушение доступа к памяти. Это предположительно является необработанным исключением, которое убивает IDE, когда компиляция выполняется в процессе.

Мой совет заключается в том, что вы отправляете отчет об ошибке в Портал качества. Это единственный способ устранить дефект. Хотя не ожидайте, что какое-либо исправление появится в XE3.

Ответ 2

Обходное решение, которое вы можете использовать здесь, - это отменить условную реализацию if и тем самым полностью исключить команду Exit.

Поэтому вместо использования

function ProcessNumber(const iNumber: Integer): Boolean; inline;
begin
  if iNumber = 0 then begin
    Result := False;
    Exit;
  end;
  // some code here ...
  Result := True;
end;

использование

function ProcessNumber(const iNumber: Integer): Boolean; inline;
begin
  if iNumber <> 0 then begin
    // some code here
    Result := True;
  end;
  else
    Result := False;
    //No exit needed here as this is already at the end of your method
end;