Директивы компилятора
директивы условной компиляции
<$C+>и <$C->— директивы проверки утверждений
<$I+>и <$I->— директивы контроля ввода/вывода
<$M>и <$S>— директивы, определяющие размер стека
<$M+>и <$M->— директивы информации времени выполнения о типах
<$Q+>и <$Q->— директивы проверки переполнения целочисленных операций
<$R>— директива связывания ресурсов
<$R+>и <$R->— директивы проверки диапазона
<$APPTYPE CONSOLE>— директива создания консольного приложения
1) Директивы компилятора, разрешающие или запрещающие проверку утверждений
По умолчанию <$C+>или
Область действия локальная
Директивы компилятора $C разрешают или запрещают проверку утверждений. Они влияют на работу процедуры Assert,используемой при отладке программ. По умолчанию действует
директива <$C+>и процедура Assert генерирует исключение EAssertionFailed, если проверяемое утверждение ложно.
Так как эти проверки используются только в процессе отладки программы, то перед ее окончательной компиляцией следует указать директиву <$C->. При этом работа процедур Assert будет блокировано и генерация исключений EassertionFailed производиться не будет.
Директивы действуют на весь файл исходного кода независимо от того, в каком месте файла они расположены.
2) Директивы компилятора, включающие и выключающие контроль файлового ввода-вывода
По умолчанию <$I+>или
Область действия локальная
Директивы компилятора $I включают или выключают автоматический контроль результата вызова процедур ввода-вывода Object Pascal. Если действует директива <$I+>, то при возвращении процедурой ввода-вывода ненулевого значения генерируется исключение EInOutError и в его свойство errorcode заносится код ошибки. Таким образом, при действующей директиве <$I+>операции ввода-вывода располагаются в блоке try. except, имеющем обработчик исключения EInOutError. Если такого блока нет, то обработка производится методом TApplication.HandleException.
Если действует директива <$I->, то исключение не генерируется. В этом случае проверить, была ли ошибка, или ее не было, можно, обратившись к функции IOResult. Эта функция очищает ошибку и возвращает ее код, который затем можно анализировать. Типичное применение директивы <$I->и функции IOResult демонстрирует следующий пример:
В этом примере на время открытия файла отключается проверка ошибок ввода вывода, затем она опять включается, переменной i присваивается значение, возвращаемое функцией IOResult и, если это значение не равно нулю (есть ошибка), то предпринимаются какие-то действия в зависимости от кода ошибки. Подобный стиль программирования был типичен до введения в Object Pascal механизма обработки исключений. Однако сейчас, по-видимому, подобный стиль устарел и применение директив $I потеряло былое значение.
3) Директивы компилятора, определяющие размер стека
Область действия глобальная
Локальные переменные в процедурах и функциях размещаются в стеке приложения. При каждом вызове процедуры или функции ее локальные переменные помещаются в стек. При выходе из процедуры или функции эти локальные процедуры удаляются из стека. Директивы компилятора $M задают параметры стека приложения: его минимальный и максимальный размеры. Приложение всегда гарантированно имеет размер стека, равный его минимальной величине. Если при запуске приложения Windows обнаруживает, что не может выделить этот минимальный объем памяти, то выдается сообщение об этой ошибке.
Если во время работы выясняется, что минимального размера стека не хватает, то размер увеличивается на 4 K, но не более, чем до установленного директивой максимального размера. Если увеличение размера стека невозможно из-за нехватки памяти или из-за достижения его максимальной величины, генерируется исключение EStackOverflow. Минимальный размер стека по умолчанию равен 16384 (16K). Этот размер может изменяться параметром minstacksize директивы <$M>или параметром number директивы <$MINSTACKSIZE>.
Максимальный размер стека по умолчанию равен 1,048,576 (1M). Этот размер может изменяться параметром maxstacksize директивы <$M>или параметром number директивы <$MAXSTACKSIZE number>. Значение минимального размера стека может задаваться целым числом в диапазоне между1024 и 2147483647. Значение максимального размера стека должно быть не менее минимального размера и не более 2147483647. Директивы задания размера стека могут включаться только в программу и не должны использоваться в библиотеках и модулях.
В Delphi 1 имеется процедура компилятора <$S>, осуществляющая переключение контроля переполнения стека. Теперь этот процесс полностью автоматизирован и директива <$S>оставлена только для обратной совместимости.
4) Директивы компилятора, включающие и выключающие генерацию информации времени выполнения о типах (runtime type information — RTTI)
По умолчанию <$M->или
Область действия локальная
Директивы компилятора $I включают или выключают генерацию информации времени выполнения о типах (runtime type information — RTTI). Если класс объявляется в состоянии <$M+>или является производным от класса объявленного в этом состоянии, то компилятор генерирует RTTI о его полях, методах и свойствах, объявленных в разделе published. В противном случае раздел published в классе не допускается. Класс TPersistent, являющийся предшественником большинства классов Delphi и все классов компонентов, объявлен в модуле Classes в состоянии <$M+>. Так что для всех классов, производных от него, заботиться о директиве <$M+>не приходится.
5) Директивы компилятора, включающие и выключающие проверку переполнения при целочисленных операциях
По умолчанию <$Q->или
Область действия локальная
Директивы компилятора $Q включают или выключают проверку переполнения при целочисленных операциях. Под переполнением понимается получение результата, который не может сохраняться в регистре компьютера. При включенной директиве <$Q+>проверяется переполнение при целочисленных операциях +, -, *, Abs, Sqr, Succ, Pred, Inc и Dec. После каждой из этих операций размещается код, осуществляющий соответствующую проверку. Если обнаружено переполнение, то генерируется исключение EIntOverflow. Если это исключение не может быть обработано, выполнение программы завершается.
Директивы $Q проверяют только результат арифметических операций. Обычно они используются совместно с директивами <$R>, проверяющими диапазон значений при присваивании. Директива <$Q+>замедляет выполнение программы и увеличивает ее размер. Поэтому обычно она используется только во время отладки программы. Однако, надо отдавать себе отчет, что отключение этой директивы приведет к появлению ошибочных результатов расчета в случаях, если переполнение действительно произойдет во время выполнении программы. Причем сообщений о подобных ошибках не будет.
6) Директива компилятора, связывающая с выполняемым модулем файлы ресурсов
Область действия локальная
Директива компилятора <$R>указывает файлы ресурсов (.DFM, .RES), которые должны быть включены в выполняемый модуль или в библиотеку. Указанный файл должен быть файлом ресурсов Windows. По умолчанию расширение файлов ресурсов — .RES. В процессе компоновки компилированной программы или библиотеки файлы, указанные в директивах <$R>, копируются в выполняемый модуль. Компоновщик Delphi ищет эти файлы сначала в том каталоге, в котором расположен модуль, содержащий директиву <$R>, а затем в каталогах, указанных при выполнении команды главного меню Project | Options на странице Directories/Conditionals диалогового окна в опции Search path или в опции /R командной строки DCC32.
При генерации кода модуля, содержащего форму, Delphi автоматически включает в файл .pas директиву <$R *.DFM>, обеспечивающую компоновку файлов ресурсов форм. Эту директиву нельзя удалять из текста модуля, так как в противном случае загрузочный модуль не будет создан и сгенерируется исключение EResNotFound.
7) Директивы компилятора, включающие и выключающие проверку диапазона целочисленных значений и индексов
По умолчанию <$R->или
Область действия локальная
Директивы компилятора $R включают или выключают проверку диапазона целочисленных значений и индексов. Если включена директива <$R+>, то все индексы массивов и строк и все присваивания скалярным переменным и переменным с ограниченным диапазоном значений проверяются на соответствие значения допустимому диапазону. Если требования диапазона нарушены или присваиваемое значение слишком велико, генерируется исключение ERangeError. Если оно не может быть перехвачено, выполнение программы завершается.
Проверка диапазона длинных строк типа Long strings не производится. Директива <$R+>замедляет работу приложения и увеличивает его размер. Поэтому она обычно используется только во время отладки.
Директива компилятора, связывающая с выполняемым модулем файлы ресурсов
Область действия локальная
Директива компилятора <$R>указывает файлы ресурсов (.DFM, .RES), которые должны быть включены в выполняемый модуль или в библиотеку. Указанный файл должен быть файлом ресурсов Windows. По умолчанию расширение файлов ресурсов — .RES. В процессе компоновки компилированной программы или библиотеки файлы, указанные в директивах <$R>, копируются в выполняемый модуль. Компоновщик Delphi ищет эти файлы сначала в том каталоге, в котором расположен модуль, содержащий директиву <$R>, а затем в каталогах, указанных при выполнении команды главного меню Project | Options на странице Directories/Conditionals диалогового окна в опции Search path или в опции /R командной строки DCC32.
При генерации кода модуля, содержащего форму, Delphi автоматически включает в файл .pas директиву <$R *.DFM>, обеспечивающую компоновку файлов ресурсов форм. Эту директиву нельзя удалять из текста модуля, так как в противном случае загрузочный модуль не будет создан и сгенерируется исключение EResNotFound.
Delphi. Условная компиляция. Краткий справочник
Условная компиляция предназначена для управления компиляцией программного кода. В Delphi имеется несколько способов её реализации, но в основном используются только четыре.
В этой реализации условная директива <$IFDEF …>проверяет, был ли определён указанный в ней символ условной компиляции. Если да, то код программы между директивами <$IFDEF …>и <$ENDIF>компилируется. В противном случае, код между этими двумя директивами компилироваться не будет.
Эта реализация отличается от предыдущей наличием директивы <$ELSE>. В этом случае, если условный оператор определён, будет компилироваться код программы между директивами <$IFDEF>и <$ELSE>. В противном случае, будет компилироваться код программы между директивами <$ELSE>и <$ENDIF>.
По сути, первая и вторая реализации ведут себя как краткая и полная форма обычного условного оператора if.
Как определить символ условной компиляции? Для этого также существует два способа.
Первый – использование директивы
Второй способ. Определить его в свойствах проекта. Для этого в меню Project нужно выбрать пункт Options и в поле Conditional defines ввести символ условной компиляции.
Третий и четвёртый способы являются аналогией первого и второго соответственно. Отличие в том, что используется условная директива <$IFNDEF>. Эта директива проверяет, что указанный символ не определён. То есть, является прямой противоположностью директивы <$IFDEF>.
В случае <$IFNDEF>, код между этой директивой и <$ENDIF>либо <$ELSE>будет скомпилирован, только если указанный в ней символ условной компиляции не определён. В остальном, принцип реализации аналогичен приведённому для директивы <$IFDEF>:
В Delphi уже имеется ряд символов условной компиляции. Вот их «классический» набор.
Значение | |
MSWINDOWS | Код компилируется только в ОС Windows |
WIN32 | То же самое, только код компилируется лишь для 32-разядной ОС. |
LINUX | Был введён в Delphi 6 вместе с MSWINDOWS для определения платформы, для которой необходимо компилировать тот или иной код.Так как компиляция для Linux в Delphi до сих пор отсутствует, то использование этого символа в программах не имеет смысла. |
CONSOLE | Консольное приложение |
CPU386 | Компиляция для процессоров типа i386 или более современных. Так как речь идёт о процессорах типа i386, использование данного символа уже давно потеряло актуальность. |
CONDITIONAL EXPRESSIONS | Проверяет использование директив $IF |
Также в число «классических» входит и символ VERxxx, который указывает конкретную версию компилятора. По сути, это целое семейство символов условной компиляции, в которое с выходом новой версии Delphi добавляется новый символ соответствующий этой версии. Ниже представлена таблица соответствия версий Delphi символам условной компиляции VERxxx (материал взят с Исходники.ру).
Символ условной компиляции | |
1 | VER80 |
2 | VER90 |
3 | VER100 |
4 | VER120 |
5 | VER130 |
6 | VER140 |
7 | VER150 |
8 | VER160 |
2005 | VER170 |
2006 | VER180 |
2007* | VER180 или VER185 |
2009 | VER200 |
2010 | VER210 |
XE | VER220 |
XE2 | VER230 |
XE3 | VER240 |
XE4 | VER250 |
XE5 | VER260 |
XE6 | VER270 |
XE7 | VER280 |
XE8 | VER290 |
10 Seatle | VER300 |
10.1 Berlin | VER310 |
10.2 Tokyo | VER320 |
*-версии 2006 и 2007 совместимы между собой на уровне двоичного кода. Поэтому, для поддержки обеих версий следует использовать символ VER180. Если необходима поддержка только версии 2007, необходимо использовать символ VER185.
После выхода в 2011 году кроссплатформенной библиотеки FireMonkey, были введены новые символы условной компиляции для MacOS и iOS. А, в 2013 году с появлением поддержки Android был введён и специальный символ условной компиляции для этой ОС. Ниже представлен перечень этих символов.
Символ условной компиляции | |
MacOS | MACOS |
iOS | IOS |
Android | ANDROID |
Условная компиляция на примере кроссплатформенного приложения:
$Warnings — Директива компилятора Delphi
Елена Филиппова, Королевство Дельфи
15 апреля 2003г.
Каждая программа содержит по крайней мере одну ошибку
Народная мудрость
Никогда не делает ошибок тот, кто просто ничего не делает. Это тоже народная мудрость. Поэтому с ошибками в коде сталкивается в своей работе каждый программист. После того, как программа успешно откомпилирована, преодолен первый этап борьбы. :о)
Не секрет, что гораздо сложнее бороться с ошибками, возникающими во время выполнения программы, особенно, когда они приводят не просто к ее «падению», а к неадекватной работе, наслаивая проблемы и создавая «наведенные» ошибки. И здесь уже надежды на компилятор нет. Спасение утопающих, как известно, дело рук этих самых утопающих.
Материал данной статьи не имеет отношения к теме тестирования и отладки. Он предназначен начинающим программистам, дабы обратить их внимание на «соломинку», которую протягивает утопающим IDE Delphi в нелегком деле борьбы с ошибками :о) Ведь не зря же ее называют дружественной средой разработки.
Хочу сразу обратить ваше внимание на то, что все приводимые примеры не являются реальными, они специально упрощены и только иллюстрируют объяснение материала.
Типы сообщений компилятора
Информацию о результате компиляции и сборки программы можно увидеть в окне, показывающем процесс компиляции , и на панели сообщений, встроенной в редактор кода .
рис. 1 Сообщения компилятора бывают трех типов. В этом списке они приведены по убыванию степени опасности, если так можно выразиться :о)
- Error — ошибка
- Warning — предупреждение
- Hint — подсказка или совет.
Довольно распространенное отношение начинающих программистов к этим сообщениям заключается в полном игнорировании предупреждений и советов. Ведь не ошибки же? Программа откомпилирована и запускается на исполнение. И, может быть, даже работает :о)
Мне приходилось встречать на некоторых форумах «дружеские советы» новичкам, сводившиеся к предложению «не обращать на эту ерунду внимания, это оптимизатор у Delphi выделывается.»
Так ли это на самом деле?
При наличии в проекте ошибок-Errors , не будет сформирован исполняемый файл и, волей не волей, ошибки придется исправлять. Наличие же сообщений Hints и Warnings позволяет запускать приложение. Обратите внимание на окно процесса компиляции (рис. 1) , в строке «Done» написано не Compiled , что, в общем-то, ожидалось, а предупреждение There are warnings . Несмотря на отсутствие ошибок, проект откомпилирован с тремя «подсказками» и пятью «предупреждениями».
Насколько безопасно не обращать на это внимание? Начнем с самых безобидных сообщений компилятора, с его советов — Hints .
Безобидные(?) Hints
Ниже приведен код простой функции, которая не содержит синтаксических ошибок, но при её компиляции будет получено три Hint’а (в коде они отмечены красным). Давайте разберем их подробно.
Variable ‘i’ is declared but never used in ‘FunctonName’ Переменная ‘i’ определена, но никогда не используется в ‘FunctonName’ — это одно из самых часто встречающихся сообщений. Чаще всего оно просто говорит о неаккуратном коде. Однако, наличие таких переменных в принципе может означать потенциальную ошибку в реализации алгоритма, ведь зачем-то она была объявлена. Именно поэтому компилятор обращает ваше внимание на эту переменную: вдруг вы просто забыли доделать задуманное?
Простейшее решение — удалить все неиспользованные переменные. А заодно и проверить, действительно ли они не нужны :о)
Value assigned to ‘j’ never used Значение, присвоенное ‘j’ никогда не используется . Это сообщение не означает, что программа неправильная — оно означает только то, что компилятор обнаружил, что после присвоения переменной j значения 0 , эта переменная не участвует более ни в каких операциях. Что делает это присвоение абсолютно бессмысленным. И, если используется оптимизатор, оно будет удалено в откомпилированном коде.
Так же, как и предыдущий Hint, это сообщение чаще всего является признаком «мусора» в коде, от которого следует избавляться, чтобы не пропустить потенциальные ошибки. Опасность в том, что в реальности может оказаться, что это присвоение было сделано не той переменной, которой нужно. Например, надо было присвоить что-то переменной i , а присвоили j .
FOR or WHILE loop executes zero times — deleted Цикл FOR или WHILE исполняется ноль раз — удалено. Собственно, текст этого сообщения полностью объясняет ситуацию. Конечно же это не специально, это «рука дрогнула», «глаз замылился» или что-то в таком духе. И компилятору остается только сказать спасибо.
Итак, получается, что Hint’ы обращают наше внимание на странности и несуразицы в коде с точки зрения «правильного» компилятора. Конечно, приведенный пример очень прост и надуман и может не убедить вас, но если в коде функции, которая содержит не один десяток операторов, появляется hint, стоит обратить на него внимание, поверьте.
Рассмотренные выше ситуации можно и нужно исправлять. Но бывают случаи, когда нет возможности исправить код так, чтобы не получать Hint’s при компиляции. Рассмотрим небольшой пример по созданию собственных классов:
Overriding virtual method ‘TLists.Clear’ has a lower visibility (private) than base class (public) Переопределенный виртуальный метод ‘TLists.Clear’ имеет видимость ниже, чем в базовом классе Это не то, чтобы ошибка, но на практике понижение видимости свойств и методов класса встречается довольно редко и говорит об ошибках на этапе проектирования базовых классов. Это понижение видимости может создать в проблему в будущем, если от класса TLists будут наследоваться при создании новых классов.
Private symbol ‘FutureTools’ declared but never used Приватный символ ‘FutureTools’ определен, но никогда не используется . Это сообщение сродни уже описанному Variable ‘ ‘ is declared but never used.
Так как этот метод приватный, то он по определению не может быть доступен нигде более, как внутри класса. Тем не менее, компилятор там его использования не обнаруживает. Из чего следует естественный вывод, что функция ‘FutureTools’ нигде не будет использоваться.
Допустим, что в этом случае все не так просто, как это видится компилятору и функция FutureTools, например, нигде не используется вовсе не потому, что вы о ней забыли или она никому не нужна. Возможно это задел на будущее. Можно, конечно, закомментировать и объявление функции и код ее реализации до поры до времени. Но можно сделать и иначе, несколько изящнее.
Возможно, что по условию конкретной задачи понижение видимости метода в классе TLists оправдано, а корректировать код базового класса нет возможности, тогда придется попросить компилятор не принимать во внимание эту ситуацию.
Как раз для таких случаев предусмотрена сцециальная дирректива компилятора: <$HINTS OFF>. Она отключает проверку кода на предмет обнаружения Hint’ов до тех пор, пока в коде не встретится обратная дирректива — <$HINTS ON>. Если в обрамленном этими специальными комментариями коде и будут «опасные» Hint-ситуации, они будут игнорироваться компилятором.
Воспользовавшись этими диррективами, мы получим код, который компилируется не только без ошибок, но и без Hint’ов:
Примечание:
Не поддавайтесь искушению раз и навсегда «заткнуть» с помощью <$HINTS OFF>упрямый компилятор, пользы от этого вам, как программисту, не будет никакой.
О пользе сообщений компилятора
Небольшое лирическое отступление:
В каждом уважающем себя форуме есть список вопросов, признанных как off-topic. Часть из них сто раз уже разжевана, часть решается нажатием клавиши F1 и так далее. На каждом форуме борятся с ними по-своему, но, к огромному сожалению, задающих такие вопросы не становится меньше. Более того, вопрошающие частенько еще и обижаются, когда их отсылают :о) Вот пример классического off-topic’а:
В ответ на такой вопрос, господа, как правило, начинают страшно ругаться. :о) Самые вежливые слова, которые получает автор вопроса, звучат примерно так — «Сколько же можно?! Хелп когда научитесь читать?!» На что автор, как ему кажется, абсолютно справедливо, начинает огрызаться, что типа, откуда ему было знать, что такое абстрактный метод и что на этом самом TStrings не написано, какие у него методы!
Проведем маленький эксперимент и напишем такой код:
При компиляции нам будет выдан warning , как раз на той строке, где создается экземпляр класса — Constructing instance of ‘TStrings’ containing abstract methods . Я надеюсь, что текст этого предупреждения абсолютно ясен и не требует пояснений.
Смотрите, что получается, ошибок компиляции нет, человек с высоко поднятой головой игнорирует «всю эту ерунду» и просто не обращает внимания на предупреждения компилятора! В итоге, он получает ошибку времени выполнения, некоторое личное недоумение, кучу словесных тычков и подзатыльников на форуме. А ведь его предупреждали! :о)
IDE Delphi, как дружественная среда программирования, кроме обычного факта уведомления о сообщениях компилятора, предоставляет дополнительные возможности — если дважды кликнуть на тексте сообщения (рис. 2), то курсор автоматически переместиться на ту строку в редакторе кода, в которой, по мнению компилятора, возникает спорная ситуация. Если же на тексте сообщения ( hint или warning ) нажать F1 , то откроется окно справочной системы (рис. 3) по конкретному hint’у или warning’у. Там будет описано, в каких случаях компилятор выдает такое сообщение и что Delphi вообще «думает» по этому поводу.
Коварные Warnings
Предупреждения- warnings обладают гораздо более высоким уровнем опасности с точки зрения компилятора. История с абстрактным классом служит тому примером. Разберем еще несколько случаев возникновения warning ‘ов: Return value of function ‘VarCompare’ might be undefined Значение результата функции ‘VarCompare’ может быть неопределено .
Казалось бы, с точки зрения логики в тексте функции все верно. Перекрыты все возможные случаи и сообщение компилятора выглядит несколько неуместно. Но не стоит ждать от него слишком много, компилятор не может (да и не обязан) вникать в логику программы. Для того, чтобы избавиться от этого сообщения, было бы правильно переписать это код. Например, вот так:
В итоге и компилятор «отстанет», и код будет более читабельным. Это сообщение только на первый взгляд кажется безобидным, ниже приведен пример, в котором возникает аналогичное предупреждение и содержится реальная ошибка — если возникнет исключительная ситуация при открытии файла, результат функции, действительно, не будет определен. В итоге это скажется при выполнении программы, когда ошибки никто не будет ожидать.
Еще один пример коварного warning ‘а: Variable ‘list’ might not have been initialized Переменная ‘list’ может быть не инициализирована .
Совершенно справедливое замечание. Если во время работы программы в функцию будет передана пустая строка, нам обеспечен знаменитый Access violation .
Вернемся еще раз к примеру с определением собственных классов.
Method ‘Clear’ hides virtual method of base type ‘TList’ Метод ‘Clear’ прячет виртуальный метод базового класса ‘TList’ . Эта ситуация буквально означает перекрытие виртуального метода родительского класса. То есть, в классе TExLists определен статический метод, имя которого совпадает с виртуальным методом родительского класса TList. Если в дальнейшем, от класса TExLists будут наследоваться, то метод Clear для этих наследников будет закрыт. Правильный вариант:
Точно также, как и в случае с hint’ами, существуют опции для отключения сообщений компилятора о предупреждениях — , и для их включения — . И точно так же хочу обратить внимание на нежелательность использования этих опций без нужды. Молчание компилятора в этом случае не будет означать отсутствие проблемы :о)
Резюме
Цель этого материала, не рассказать обо всех возможных hint ‘ах и warning ‘ах, их список слишком велик для одной статьи, а обратить внимание на необходимость анализировать ВСЕ сообщения компилятора в ваших программах.
Елена Филиппова
Специально для Королевства Delphi
Идентификаторы $ в Delphi WARN директивы компилятора
December 2020
14.4k раз
Delphi имеет $ WARN директивы компилятора, что позволяет селективно включить или отключить конкретные предупреждения. Delphi 2009 файл справки описывает синтаксис:
Но это только перечисляет идентификаторы 6 предупреждений.
Я хотел бы иметь полный список всех идентификаторов предупреждения. В частности, я хочу знать идентификаторы неявной строки литых предупреждений W1057 и W1058 в Delphi 2009.
Мне удалось угадать один для неявного ANSI-> отбрасывает Unicode (W1057):
Погуглить за что нашел меня другой:
Хотя это решает мою насущную потребность, я все же хотел бы знать полный список идентификаторов предупреждения. Такие вещи, как это должны быть документированы.
4 ответы
Что-то еще не упоминается в документации по Delphi 2009:
В $ WARN директивы теперь имеет 3-ий вариант ERROR в дополнение к ON и OFF. Таким образом, вы можете иметь:
Такие вещи, как это должно быть документально
На сегодняшний день полный список идентификаторов и их номеров предупреждения компилятора приведены в документации по адресу:
Выдержка:
Идентификатор в $ WARN директива может иметь любое из следующих значений:
Я посмотрел через помощь и не видел полный список . так ковыряться кода оказывается постоянные предупреждения компилятора все перечисленные в: CodeGear \ RAD Studio \ 6.0 \ Sources \ toolsapi \ DCCStrs.pas
Поиск «Implicit_String_Cast_Loss», и вы увидите, что константа sIMPLICIT_STRING_CAST_LOSS = «DCC_IMPLICIT_STRING_CAST_LOSS»;
Я бы предположил, остальные строки DCC_xxx с соответствующим X_true / _false / _error Определяет то, что вы после этого.
Интернет помощь была не очень хорошо, так как Delphi 7.
Право Darian о том, что DCCStrs.pas перечислены идентификаторы, используемые компилятором Delphi. Это не приходило в голову искать источник, так как Delphi не включает в себя источник для его составителя.
Я извлек идентификаторы для подсказок и предупреждений от этого файла:
Директива компилятора региона Delphi — файлы с совместимостью в обратном направлении?
Учитывая желание использовать полезную директиву компилятора Region в файлах модулей, какой лучший подход позволяет использовать эти же устройства в предыдущих версиях Delphi? Похоже, что нет «приличного» подхода. (Желаемая версия IDE — Delphi 7)
Мне нравится иметь регионы над определениями методов, чтобы скрыть/отобразить рекомендации по определению метода и комментарии к истории версий, но мне пришлось бы окружать директивы Region другими командами компилятора, которые вроде бы убивают «чистка» региональных компиляторов.
Я полагаю, что препроцессор можно было бы написать, чтобы прокомментировать все директивы Region/EndRegion, если используется версия Delphi, которая не поддерживает регионы .. и затем добавляет обратно для более поздних версий?
Я не на 100% перешел на Delphi 2009 и должен поддерживать несколько версий IDE.
Создан 18 апр. 09 2009-04-18 23:34:48 Darian Miller
2 ответа
Я предполагаю, что D7 не хочет переписывать <$ REGION>или <$ ENDREGION>? У меня установлен только D2007/9 и не могу это проверить.
D2009 редактор создает область, как и ожидалось. D7 должен игнорировать $ REGION/$ ENDREGION, если «undef» не определен.
Создан 19 апр. 09 2009-04-19 07:14:16 gabr
+1. Положите на одну строку и создайте с помощью кода или живого шаблона, это не убивает чистоты и не требует больше усилий писать. – mghie 19 апр. 09 2009-04-19 10:36:49
Это работает . и будет отмечен как ответ, как указано в первоначальном вопросе. Мой реальный ответ — удалить Регионы на данный момент и переключить все на 2009, как позволяет время. – Darian Miller 22 апр. 09 2009-04-22 02:38:03
Есть несколько компонентов для улучшения редактора Delphi (7), которые обеспечивают что-то вроде этого. Думаю GExperts.
Если вы в порядке с вашим кодом, вы можете рассмотреть <$ I>, чтобы разделить большие файлы.
Создан 20 апр. 09 2009-04-20 07:39:57 Stijn Sanders
. или просто разделить устройство на несколько единиц! О директиве $ INCLUDE, из моего эксперимента, $ I не работает в среде Delphi. Например, в навигаторе кода есть проблемы с просмотром кода во вложенных файлах. Нет проблем с компилятором, но с Delphi IDE. Напротив, у Lazarus нет проблем при использовании нескольких файлов INCLUDEd и обрабатывать их как обычные .pas-файлы. – Arnaud Bouchez 13 мар. 15 2015-03-13 08:38:37
$Warnings — Директива компилятора Delphi
Как сделать свои собственные сообщения при компилляции
Как узнать версию компиллятора ?
Какие есть директивы компилятора?
<$I+>и <$I->— директивы контроля ввода/вывода
<$M>и <$S>— директивы, определяющие размер стека
<$M+>и <$M->— директивы информации времени выполнения о типах
<$Q+>и <$Q->— директивы проверки переполнения целочисленных операций
<$R>— директива связывания ресурсов
<$R+>и <$R->— директивы проверки диапазона
<$APPTYPE CONSOLE>— директива создания консольного приложения
1) Директивы компилятора, разрешающие или запрещающие проверку утверждений.
По умолчанию <$C+>или <$ASSERTIONS ON>
Область действия локальная
Директивы компилятора $C разрешают или запрещают проверку утверждений. Они влияют на работу процедуры Assert,используемой при отладке программ. По умолчанию действует
директива <$C+>и процедура Assert генерирует исключение EAssertionFailed , если проверяемое утверждение ложно.
Так как эти проверки используются только в процессе отладки программы, то перед ее окончательной компиляцией следует указать директиву <$C->. При этом работа процедур Assert будет блокировано и генерация исключений EassertionFailed производиться не будет.
Директивы действуют на весь файл исходного кода независимо от того, в каком месте файла они расположены.
2) Директивы компилятора, включающие и выключающие контроль файлового ввода-вывода.
По умолчанию <$I+>или <$IOCHECKS ON>
Область действия локальная
Директивы компилятора $I включают или выключают автоматический контроль результата вызова процедур ввода-вывода Object Pascal . Если действует директива <$I+>, то при возвращении процедурой ввода-вывода ненулевого значения генерируется исключение EInOutError и в его свойство errorcode заносится код ошибки. Таким образом, при действующей директиве <$I+>операции ввода-вывода располагаются в блоке try . except , имеющем обработчик исключения EInOutError . Если такого блока нет, то обработка производится методом TApplication.HandleException .
Если действует директива <$I->, то исключение не генерируется. В этом случае проверить, была ли ошибка, или ее не было, можно, обратившись к функции IOResult . Эта функция очищает ошибку и возвращает ее код, который затем можно анализировать. Типичное применение директивы <$I->и функции IOResult демонстрирует следующий пример:
AssignFile ( F,s );
Rewrite (F);
<$I+>
i:=IOResult ;
if i <> 0 then
case i of
2 : .
3 : .
end ;
В этом примере на время открытия файла отключается проверка ошибок ввода вывода, затем она опять включается, переменной i присваивается значение, возвращаемое функцией IOResult и, если это значение не равно нулю (есть ошибка), то предпринимаются какие-то действия в зависимости от кода ошибки. Подобный стиль программирования был типичен до введения в Object Pascal механизма обработки исключений. Однако сейчас, по-видимому, подобный стиль устарел и применение директив $I потеряло былое значение.
3) Директивы компилятора, определяющие размер стека
По умолчанию <$M 16384,1048576>
Область действия глобальная
Локальные переменные в процедурах и функциях размещаются в стеке приложения. При каждом вызове процедуры или функции ее локальные переменные помещаются в стек. При выходе из процедуры или функции эти локальные процедуры удаляются из стека.
Директивы компилятора $M задают параметры стека приложения: его минимальный и максимальный размеры. Приложение всегда гарантировано имеет размер стека, равный его минимальной величине. Если при запуске приложения Windows обнаруживает, что не может выделить этот минимальный объем памяти, то выдается сообщение об этой ошибке.
Если во время работы выясняется, что минимального размера стека не хватает, то размер увеличивается на 4 K, но не более, чем до установленного директивой максимального размера. Если увеличение размера стека невозможно из-за нехватки памяти или из-за достижения его максимальной величины, генерируется исключение EStackOverflow . Минимальный размер стека по умолчанию равен 16384 (16K). Этот размер может изменяться параметром minstacksize директивы <$M>или параметром number директивы <$MINSTACKSIZE>.
Максимальный размер стека по умолчанию равен 1,048,576 (1M). Этот размер может изменяться параметром maxstacksize директивы <$M>или параметром number директивы <$MAXSTACKSIZE number >. Значение минимального размера стека может задаваться целым числом в диапазоне между1024 и 2147483647. Значение максимального размера стека должно быть не менее минимального размера и не более 2147483647. Директивы задания размера стека могут включаться только в программу и не должны использоваться в библиотеках и модулях.
В Delphi 1 имеется процедура компилятора <$S>, осуществляющая переключение контроля переполнения стека. Теперь этот процесс полностью автоматизирован и директива <$S>оставлена только для обратной совместимости.
4) Директивы компилятора, включающие и выключающие генерацию информации времени выполнения о типах ( runtime type information — RTTI).
По умолчанию <$M->или <$ TYPEINFO OFF>
Область действия локальная
Директивы компилятора $M включают или выключают генерацию информации времени выполнения о типах ( runtime type information — RTTI). Если класс объявляется в состоянии <$M+>или является производным от класса объявленного в этом состоянии, то компилятор генерирует RTTI о его полях, методах и свойствах, объявленных в разделе published . В противном случае раздел published в классе не допускается. Класс TPersistent , являющийся предшественником большинства классов Delphi и все классов компонентов, объявлен в модуле Classes в состоянии <$M+>. Так что для всех классов, производных от него, заботиться о директиве <$M+>не приходится.
5) Директивы компилятора, включающие и выключающие проверку переполнения при целочисленных операциях
По умолчанию <$Q->или <$OVERFLOWCHECKS OFF>
Область действия локальная
Директивы компилятора $Q включают или выключают проверку переполнения при целочисленных операциях. Под переполнением понимается получение результата, который не может сохраняться в регистре компьютера. При включенной директиве <$Q+>проверяется переполнение при целочисленных операциях +, -, *, Abs , Sqr , Succ , Pred , Inc и Dec . После каждой из этих операций размещается код, осуществляющий соответствующую проверку. Если обнаружено переполнение, то генерируется исключение EIntOverflow . Если это исключение не может быть обработано, выполнение программы завершается.
Директивы $Q проверяют только результат арифметических операций. Обычно они используются совместно с директивами <$R>, проверяющими диапазон значений при присваивании.
Директива <$Q+>замедляет выполнение программы и увеличивает ее размер. Поэтому обычно она используется только во время отладки программы. Однако, надо отдавать себе отчет, что отключение этой директивы приведет к появлению ошибочных результатов расчета в случаях, если переполнение действительно произойдет во время выполнении программы. Причем сообщений о подобных ошибках не будет.
6) Директивы компилятора, включающие и выключающие проверку диапазона целочисленных значений и индексов
По умолчанию <$R>или <$RANGECHECKS OFF>
Область действия локальная
Директивы компилятора $R включают или выключают проверку диапазона целочисленных значений и индексов. Если включена директива <$R+>, то все индексы массивов и строк и все присваивания скалярным переменным и переменным с ограниченным диапазоном значений проверяются на соответствие значения допустимому диапазону. Если требования диапазона нарушены или присваиваемое значение слишком велико, генерируется исключение ERangeError . Если оно не может быть перехвачено, выполнение программы завершается.
Проверка диапазона длинных строк типа Long strings не производится.
Директива <$R+>замедляет работу приложения и увеличивает его размер. Поэтому она обычно используется только во время отладки.
6) Директива компилятора, связывающая с выполняемым модулем файлы ресурсов
Область действия локальная
Директива компилятора <$R>указывает файлы ресурсов (.DFM, .RES), которые должны быть включены в выполняемый модуль или в библиотеку. Указанный файл должен быть файлом ресурсов Windows . По умолчанию расширение файлов ресурсов — .RES.
В процессе компоновки компилированной программы или библиотеки файлы, указанные в директивах <$R>, копируются в выполняемый модуль. Компоновщик Delphi ищет эти файлы сначала в том каталоге, в котором расположен модуль, содержащий директиву <$R>, а затем в каталогах, указанных при выполнении команды главного меню Project | Options на странице Directories / Conditionals диалогового окна в опции Search path или в опции /R командной строки DCC32.
При генерации кода модуля, содержащего форму, Delphi автоматически включает в файл . pas директиву <$R *.DFM>, обеспечивающую компоновку файлов ресурсов форм. Эту директиву нельзя удалять из текста модуля, так как в противном случае загрузочный модуль не будет создан и генерируется исключение EResNotFound .
Все установленные в настройках опции компиляции можно вставить непосредственно в текст программы нажав клавиши Ctrl-O , O
Как сделать свои собственные сообщения при компилляции ?
destructor TumbSelectionTempTable.Destroy ;
begin
// Clear the temp tables.
<$MESSAGE Warn ' - remember to free all allocated objects'>
ClearAllOuterWorldFold ;
if FSubjectsTempTableCreated then
DropTempTable ( FTableName );
FOuterWorldsFolded.Free ;
FQuery.Free ;
inherited ;
end ;
Работает только в Дельфи 6/7
Как узнать версию компилятора?
Иногда надо выполнить разный код в зависимости от версии Дельфи , особенно актуально это при разработки компонентов и модулей, которые используются в разных приложениях.
В Дельфи предопределены специальные константы компиляции для этого:
Ver80 — Дельфи 1
Ver90 — Дельфи 2
Ver93 — С Buider 1
Ver100 — Дельфи 3
Ver110 — С Buider 3
Ver120 — Дельфи 4
Ver125 — С Buider 4
Ver130 — Дельфи 5
Ver140 — Дельфи 6
Ver150 — Дельфи 7
procedure TForm1.Button2Click( Sender : TObject );
const Version=
Идентификаторы директивы компилятора Delphi $ WARN
В Delphi есть директива компилятора $ WARN, которая позволяет выборочно включать или отключать определенные предупреждения. Файл справки Delphi 2009 описывает синтаксис:
Но он отображает только идентификаторы для 6 предупреждений.
Я хотел бы иметь полный список всех предупреждающих идентификаторов. В частности, я хочу знать идентификаторы для неявных строковых предупреждений о переносе W1057 и W1058 в Delphi 2009.
I managed to guess the one for implicit Ansi->Unicode casts (W1057):
Гуглинг за это нашел меня другой:
Хотя это и решает мою непосредственную потребность, мне все же хотелось бы узнать полный список предупреждающих идентификаторов. Такие вещи должны быть задокументированы.
$Warnings — Директива компилятора Delphi
Профиль
Группа: Участник Клуба
Сообщений: 3497
Регистрация: 31.3.2002
Где: Лес
Репутация: 14
Всего: 115
DriveSoftware |
|
|