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

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

Симптом

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

"dcc" завершился с кодом 1.

или, что еще хуже, IDE 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. Это ошибка компилятора?
  2. Если это ошибка, есть ли обходной путь для безопасного выхода из встроенной функции?

person Astaroth    schedule 07.06.2015    source источник
comment
Это заставляет меня задаться вопросом: вы ожидаете, что это выйдет из контекста вызывающего абонента или просто встроенной функции?   -  person TLama    schedule 07.06.2015
comment
@TLama Я думаю, что спрашивающий знает, что inline не меняет того, что exit означает. Проблема в том, что внутренняя антивирусная программа убивает IDE.   -  person David Heffernan    schedule 07.06.2015


Ответы (2)


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

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

При сборке с помощью msbuild вы получаете ошибку такой формы:

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

GPF расшифровывается как General Protection Fault, то есть нарушение доступа к памяти. Предположительно, это необработанное исключение, которое убивает IDE, когда компиляция выполняется в процессе.

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

person David Heffernan    schedule 07.06.2015
comment
Хеффернан, спасибо за ответ. Я отправил ошибку на портал качества. Я думаю, что сейчас я вынужден использовать goto labelExit как обходной путь. - person Astaroth; 07.06.2015
comment
@Astaroth - выход не всегда проблема. Вроде нормально f.i: Результат: = iNumber ‹› 0; если не Результат, то Выход; ... - person Sertac Akyuz; 07.06.2015

Один из способов обхода этой проблемы - отменить условную реализацию 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;
person SilverWarior    schedule 07.06.2015
comment
SilverWarior, я ценю ваш комментарий, так что +1 от меня. Однако в моем примере я просто показываю, что в определенных обстоятельствах оказывается, что команда Exit ведет себя неожиданно. Мой пример на самом деле не отражает мою фактическую структуру кода. Я уверен, что каждый разработчик когда-либо сталкивался с ситуацией, когда Exit непосредственно из функции - лучший доступный вариант с точки зрения эффективности. В любом случае, я согласен с вами, что иногда (как в моем примере) отказ от команды Exit не снижает производительность кода. - person Astaroth; 07.06.2015
comment
Я подозревал, что это решение не может быть таким простым, но все же вы не поверили, сколько раз вы можете пропустить даже самые простые решения. Особенно, когда вы тратите некоторое время на то, чтобы ломать голову над решением какой-то проблемы, и забываете пойти посмотреть на картину в целом и попытаться, возможно, вообще избежать этой проблемы. - person SilverWarior; 07.06.2015
comment
@Silver Реальный код, вероятно, больше, и отказ от выхода сделает функцию менее понятной. - person David Heffernan; 08.06.2015