Отключить проверку диапазона Delphi только для небольшой части кода

Как отключить проверку диапазона для части файла. Выключить легко, но как потом вернуться к настройкам проекта? Псевдокод ниже должен объяснить это:

Unit1;

//here's range checking on or off as per the project setting

code here...

{$R-}

//range checking is off here because the code causes range check errors

code here...

//now I want to revert to the project setting. How do I do that?

code here...

end.

person Giel    schedule 14.02.2011    source источник


Ответы (2)


См.: директиву IFOPT.

{$IFOPT R+}
  {$DEFINE RANGEON}
  {$R-}
{$ELSE}
  {$UNDEF RANGEON}
{$ENDIF}
//range checking is off here because the code causes range check errors
//code here...
{$IFDEF RANGEON}
  {$R+}
  {$UNDEF RANGEON}
{$ENDIF}
person Sertac Akyuz    schedule 14.02.2011
comment
Чтобы быть в полной безопасности, вы должны UNDEF RANGEON, если проверка диапазона не включена. В противном случае код некорректно включал бы проверку диапазона при компиляции с параметром /$R-/dRANGEON. - person gabr; 15.02.2011
comment
Да, это то, что я ищу. Я не знал, что $IFOPT существует. Спасибо - person Giel; 15.02.2011
comment
Мне нужно было сделать это несколько раз, в основном, когда я делаю вызовы в библиотеку (например, LockBox3), которая выдает исключения, если включена проверка переполнения и/или диапазона. Я согласен с тем, что описанная выше техника является правильным способом сделать это; однако после включения этих директив очень важно, чтобы вы собирали свой код, а не просто компилировали его, иначе переключение таинственным образом просто не сработает! - person Chris Bargh; 03.07.2014
comment
На самом деле этот образец слишком тяжелый. Этого будет достаточно: {$UNDEF RANGEON} {disable possible /d switch} {$IFOPT R+}{$DEFINE RANGEON}{$ENDIF} {save initial switch state} и использовать так {$IFDEF RANGEON} {$R+} {$ENDIF} - person Fr0sT; 08.07.2015
comment
Обратите внимание, что {$IFOPT} работает только с директивами, которые предлагают краткие однобуквенные версии. Например, это работает для {$RANGECHECKS}, у которого есть короткая версия {$R}, но не будет работать для {$HINTS}, у которого нет короткой версии. См. RSP-33621. Кроме того, проголосуйте за RSP-14045, чтобы добавить $PUSH/$POP в Delphi (FreePascal уже поддерживает его), что было бы лучшим решением этой проблемы. - person Remy Lebeau; 06.04.2021
comment
@RemyLebeau Проголосовал за оба - $PUSH/$POP было бы особенно приятно! - person J...; 06.04.2021

Оберните свой код в $R директивы:

{$R-} // disable range checking
// do non-range-checked operations here
{$R+} // turn range checking back on

Обратите внимание, что директива применяется на уровне оператора. Вы не можете обернуть этим только часть выражения.

person Rob Kennedy    schedule 14.02.2011
comment
Но {$R+} включает его, даже если он выключен в окне параметров проекта. Я хочу, чтобы он вернулся к настройке параметров проекта. Или я что-то упускаю? - person Giel; 15.02.2011
comment
Ответ Сертака охватывает это - проверьте, включен ли он, и установите символ. Затем проверьте символ и условно восстановите исходную настройку. Но чего вам не хватает, так это того, что вы никогда не должны отключать его в параметрах проекта в первую очередь. Отлавливает ошибки. - person Rob Kennedy; 15.02.2011
comment
Вы можете захотеть отключить его для сборки релиза, но вы включаете его во всех остальных случаях. Особенно для сборок, которые вы делаете для запуска тестов. - person David Heffernan; 15.02.2011
comment
Почему вы хотите отключить его для релизных сборок? - person dan-gph; 15.02.2011
comment
@dangph, чтобы выпущенная версия работала быстрее - person David Heffernan; 15.02.2011
comment
@Rob: Да, проверка диапазона выявляет ошибки, но ошибки диапазона практически неизбежны в побитовом коде и/или/коде сдвига. - person Giel; 15.02.2011
comment
Гил, я не понимаю твоей точки зрения. Если ваша вся программа не использует побитовые операции, которые имеют тенденцию выходить за пределы диапазонов ваших типов, нет причин отключать проверку диапазона глобально. Просто отключите его для небольших областей кода, которым он нужен, а затем снова включите его, чтобы он мог продолжать выявлять другие ваши ошибки. (Лично у меня не было такого неизбежного опыта, как у вас. Мне удавалось довольно хорошо их избегать.) - person Rob Kennedy; 15.02.2011
comment
@Rob: мы выключаем проверку диапазона в релизных версиях по соображениям производительности. - person Giel; 15.02.2011
comment
@ Дэвид Хеффернан, проверка диапазона будет замедлять только некоторые внутренние циклы. В большинстве. Вы можете отключить его для них (после профилирования вашего кода). Почти во всех случаях проверка диапазона не будет иметь заметного значения. Во всех других языках, кроме C и C++, он включен. Кажется, это не причиняет им вреда. Ошибки, связанные с повреждением памяти, являются одними из самых серьезных ошибок. Они могут проявляться в странном поведении и трудно воспроизводимых ошибках. ИМО рисковать не стоит. - person dan-gph; 15.02.2011
comment
@dangph Для самых внутренних циклов в моей программе все, что они делают, это считывают значения с плавающей запятой из массивов. Отключение проверки диапазона имеет небольшое значение, но это важно. - person David Heffernan; 15.02.2011
comment
@ Дэвид Хеффернан, дело в том, что вы можете отключить его локально, где вам нужно, с помощью {$R-}. Но вы можете оставить его включенным глобально в настройках проекта. - person dan-gph; 15.02.2011