PDA

Просмотр полной версии : [Урок] Обход file guard с идентичными именами



VVWVV
08.12.2016, 23:08
В данной статье я постараюсь объяснить обход защиты от повторного включения в исходный файл. Данная статья будет полезна тем, кто пишет, или собирается написать своей многофайловый проект.

Введение


Защита от повторного включения (или file guard, include guard) – защита, позволяющая избегать проблемы с повторным включением какой-либо библиотеки в исходный файл. Данный защитник работает следующем образом: генерирует константу, в названии которой содержится имя включаемого файла, и при последующем включении файла с таким же названием, защитник просто проигнорирует его. Важно отметить, что константа содержит только название файла, а не полный путь.


Проблема и решение


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

Например, в операционной системе Windows это работает так:


#include "some_dir_1\file"
#include "some_dir_2\file"


В остальных же это может работать так:


#include "some_dir_1\\\\file"
#include "some_dir_2\\\\file"

Хотя вряд ли кто-то из вас будет писать подобное.

Будет загружен лишь один файл. Это происходит из-за обратного слэша, который присутствует в данном примере. Кроме того, первая конструкция повлечёт множество ошибок, например, на других операционных системах. Советую вам использовать обычный слэш для того, чтобы избежать ошибок.

Давайте рассмотрим рабочий пример как для Windows, так и для других операционных систем.


#include "some_dir_1/file"
#include "some_dir_2/file"


Оба файла будут загружаться во всех операционных системах одинаково.


Немного советов



Для того чтобы избежать ошибок, необходимо использовать обычный слэш.
Использовать уникальные названия файлов. Кроме того, использовать теги перед этими названиями, дабы уменьшить вероятность совпадения.
Удалять генерируемую константу, используя препроцессорную директиву #undef.
В компиляторе от Zeex константа не генерируется, т.е. вышесказанной проблемы не появится. Однако, вы можете восстановить генерацию данной константы, используя флаг -Z.





Автор: VVWVV
Исключительно для pro-pawn.ru


Копирование данной статьи на других ресурсах без разрешения автора запрещено!

DeimoS
08.12.2016, 23:29
Собственно, в официальной документации к Pawn, в той части, где рассказывается про директиву #include, описан вариант с использованием "undef". Но будем честны, из всех скриптеров, что пишут скрипты для SA-MP, эту документацию открывало процентов 10. А знает о ней меньше половины.
В общем, годно :з

Daniel_Cortez
09.12.2016, 17:14
#include <directory1\filename> // Загрузится только лишь этот.
#include <directory2\filename>
#include <directory3\filename>


Обратный слэш в именах файлов работает только под вендой. Вместо того, чтобы убивать совместимость с другими ОС и искать обходные пути, таким способом не следует пользоваться вообще.

VVWVV
10.12.2016, 02:34
Обратный слэш в именах файлов работает только под вендой. Вместо того, чтобы убивать совместимость с другими ОС и искать обходные пути, таким способом не следует пользоваться вообще.

Что-то забыл, что в других системах это не работает. Забавно, если исправить это, то на разных осях это не должно работать одинаково, ведь, используя данный способ на Windows, у вас будет генерироваться совершено другое имя у константы.


_inc_a1/file


Что более приводит к несовместимости.

Windows


#include "a1/f.inc" // Загрузится
#include "a2/f.inc" // Загрузится


На других осях, например, Linux


#include "a1/f.inc" // Загрузится только этот.
#include "a2/f.inc"


P.S. возможно, что-то упускаю.

Следовательно, самым лучшем решением является компилятор от Zeex.

DeimoS
10.12.2016, 04:31
Самым лучшим решением являются уникальные имена для библиотек :pardon:

VVWVV
10.12.2016, 14:08
Самым лучшим решением являются уникальные имена для библиотек :pardon:

Имя библиотек тоже могут совпасть, хотя, если правильно назвать, то вероятность этого уменьшится. Добавил твой вариант в список.

DeimoS
10.12.2016, 15:05
Имя библиотек тоже могут совпасть

Ну так я для того и написал "уникальные" ведь :)
Сам пишу свой проект разбив на файлы и никаких проблем с именами нет.
Если всё продумывать заранее и не писать код от балды, контролировать имена не составит труда.

Да и никто не запрещает в начале каждого инклуда прописывать

#undef _inc_<имя файла>

Daniel_Cortez
11.12.2016, 10:42
Ок, подведём итоги:


Как уже правильно заметил DeimoS, одинаковых идентификаторов в защите от повторного подключения возникнуть не должно, если у автора инклуда руки растут из нужного места. И лично я тоже считаю эту проблему с одинаковыми include guard надуманной.


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


Полагаю, вывод очевиден. В таком виде эта тема не может быть перемещена в раздел для одобренных статей.

VVWVV
11.12.2016, 13:21
Ок, подведём итоги:


Как уже правильно заметил DeimoS, одинаковых идентификаторов в защите от повторного подключения возникнуть не должно, если у автора инклуда руки растут из нужного места. И лично я тоже считаю эту проблему с одинаковыми include guard надуманной.


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


Полагаю, вывод очевиден. В таком виде эта тема не может быть перемещена в раздел для одобренных статей.

UPD: Изменил пост.

DeimoS
11.12.2016, 16:29
Мне уже прилетел в личку вопрос о поводу этой части :)





В компиляторе от Zeex данная ошибка устранена. Для того чтобы вернуть данную фичу, вам необходимо использовать флаг -Z.




Уточни, что "данная ошибка/фича" - это речь о генерации макроса

#define _inc_filename

VVWVV
11.12.2016, 16:35
Мне уже прилетел в личку вопрос о поводу этой части :)


Уточни, что "данная ошибка/фича" - это речь о генерации макроса

#define _inc_filename

Очень странно, что именно тебе пишут. Лол. Исправил.