include guards
От: reversecode google
Дата: 10.01.22 00:56
Оценка: :)
народ на реддите в +100500 раз устроил флейм по поводу include guards
link

вообщем то я не поклонник секты pragma once
но в конце прошлого года на одном из собесов чуть чуть пофлудил
а сейчас решил все таки проверить
итог
пару пет проектов


git ls-files | xargs wc -l

один проект-ик

107820 total

другой проект-ик

87018 total

тестировал под виндой на msvc последним из 19
с изначальным

#ifndef _file_hpp_
#define _file_hpp_
...
#endif


и дополненными

#ifndef _file_hpp_
#define _file_hpp_
#pragma once
...
#endif


результаты не впечатлили

первый
без pragma once — 5.48 минуты
c pragma once — 4.45 минут


второй
без pragma once — 3.41 минут
c pragma once — 3.8 минут

вообщем в пределах погрешности
я бы сказал разницы особой нет

итого
не смотря на то что писанины с pragma once меньше
нарваться на проблемы с одинаковыми файлами по разным путям — больше
останусь на старом добром ifndef
Re: include guards
От: Михaил  
Дата: 10.01.22 02:59
Оценка:
Здравствуйте, reversecode, Вы писали:

R>народ на реддите в +100500 раз устроил флейм по поводу include guards


R>итого

R>не смотря на то что писанины с pragma once меньше
R>нарваться на проблемы с одинаковыми файлами по разным путям — больше
R>останусь на старом добром ifndef

А что не так с прагма уанс, можно вкратце, и почему это секта?
Re[2]: include guards
От: Андрей Тарасевич Беларусь  
Дата: 10.01.22 04:43
Оценка: +1
Здравствуйте, Михaил, Вы писали:

М>А что не так с прагма уанс, можно вкратце, и почему это секта?


Ну хотя бы то, что нет никакого "прагма уанс". Это не стандартная фича.
Best regards,
Андрей Тарасевич
Отредактировано 10.01.2022 4:44 Андрей Тарасевич . Предыдущая версия .
Re[2]: include guards
От: reversecode google
Дата: 10.01.22 05:52
Оценка: -2
М>А что не так с прагма уанс, можно вкратце, и почему это секта?

/somedir1/header_file.h
/somedir2/header_file.h

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


все на ней помешались
и если на собеседовании выражаешь свое безразличие или сомнения по ее поводу
могут зарубить и не взять
Re: Нужна ли защита от повторного включения
От: velkin Удмуртия http://blogs.rsdn.org/effective/
Дата: 10.01.22 05:55
Оценка: -1
Здравствуйте, reversecode, Вы писали:

R>останусь на старом добром ifndef


Я тоже использую страж включения, но тут нужно сразу решить, или используешь только страж включения, или только pragma once.

А ещё есть другие мысли по этому поводу. Обязательны ли эти конструкции в принципе? Что будет, если их не писать? Очевидно компилятор заругается при повторном включении, но... в случае использования защитных конструкций от повторного включения даём добро на многократные повторные включения.

Вот и ответь мне username, нужны ли стражи включения в своём личном проекте?

Может мы тут все дураки и не лечимся. Пихаем множество включений зная, что они будут проигнорированы благодаря стражу включения. А кто потом будет удалять лишние включения #inlcude? Да, никто и не будет, ведь всё и так работает.

Говорят Объектно-ориентированное программирование — катастрофа на триллион долларов, а что если стражи включения это катастрофа на триллион долларов. Из-за этих уродских макроконструкций код C/C++ становится уродливым, отвлекает программистов на его написание. Бьерн Страуструп вообще-то ратовал за исключение макросов из обихода, но стражи включения как-то пролезли даже в его идеологию.
Re[2]: Нужна ли защита от повторного включения
От: reversecode google
Дата: 10.01.22 06:06
Оценка: :)
или или
вы в стандартные хидеры M$ хоть раз смотрели ?
там и pragma once и include guards

собственно мне pragma once был любопытен с точки зрения ускорения компиляции

но после тестовых замеров
и раздумий
мне она ничего не сможет ускорить
поскольку пет проекты все мои
и что куда и зачем я инклудю, я прекрасно контролирую сам
и повторных переинклудов у меня нет

и еще я пришел к выводу что это хороший критерий оценки команды программистов которые работают над одним проектом

если использовался include guard
и в проект добавили еще и pragma once и скорость компиляции возросла
значит программисты которые работают над проектом
слабо представляют дерево зависимости и включают хидеры на глаз не понимая нужно или не нужно

типичный пример недавняя новость про ускорение компиляции линукс ядра после переоптимизации подключения хидеров

меня это посмешило
господа линукс программисты явно не в курсе про pragma once
без переоптимизаций инклудов
банальной pragma once они бы добились тех же самых ускорений при сборке ядра
Re[3]: Нужна ли защита от повторного включения
От: velkin Удмуртия http://blogs.rsdn.org/effective/
Дата: 10.01.22 06:36
Оценка:
Здравствуйте, reversecode, Вы писали:

R>или или

R>вы в стандартные хидеры M$ хоть раз смотрели ?
R>там и pragma once и include guards

А я так и делал вначале, а потом понял, что это крайне глупо. Впрочем я давно уже ушёл от инструментов майков, таких как "вижуал студио". Мне на скорость компиляции класть с высокой колокольни. Эта проблема решается многоядерной компиляцией и покупкой компьютера с более производительным процессором. И то, проект должен быть гигантским, чтобы нужно было такое делать. Но на код я смотрю самолично, а это уже другой разговор.

Да и в целом, я что обезьяна копировать за майками. Например, пихать везде stdafx.h. Нет, если используешь страж включения, то pragma once не нужен. И наоборот, начал пользоваться pragma once, то зачем городить макроконструкции. Оставайся уж тогда на страже включения из трёх макродиректив (#ifndef, #define, #endif).

R>и еще я пришел к выводу что это хороший критерий оценки команды программистов которые работают над одним проектом


Это совершенно другая тема. Мне сейчас не хочется играть в политкорректность, если наниматели используют что-то такое для оценки команды, то они дебилы. Всё же просто, для проекта должны быть правила оформления кода. Сказали писать страж включения, пишешь страж включения. Сказали писать pragma once, пишешь pragma once. Сказали делать и то и другое, делаешь и то и другое. А кто-то может не писать ничего и это будет задокументировано как обязательный стиль для проекта. А если начинаются споры, ну так и пусть катятся эти наниматели колбаской, ищут себе "единомышленников". Если для них главное идеология, а не единый прописанный в правилах проекта стиль кода.

R>меня это посмешило

R>господа линукс программисты явно не в курсе про pragma once
R>без переоптимизаций инклудов
R>банальной pragma once они бы добились тех же самых ускорений при сборке ядра

А кто такие линукс программисты? Те кто делают ядро линукса? Те кто используют системные вызовы линукса? Те кто просто программируют под линуксом? Я как человек постоянно сидящий в Debian, причём по большей части использую его как мультимедийную развлекательную платформу для всего, веб-серфинг, фильмы, игры и так далее, скажу так, мне насрать на оптимизации. А если говорить о сборщиках ядра, ну так это их проект и их дело. В проекте логично следовать принятым соглашениям чтобы код был в едином стиле.

Но вопрос остаётся открытым, а везде ли и всегда нужны конструкции предотвращающие ошибки компилятора при повторном включении?

Представь, что придёт богатый наниматель и скажет, что никаких стражей включения и pragma once быть в его проекте не должно. Что дескать нефиг включать, когда можно не включать. Всё должно быть супер продумано, а не состоять из заплат. Или другое требование, весь проект должен быть в одном файле. А почему бы и нет. Конечно, кто-то скажет, что я сейчас выдумываю, но неудобная правда в том, что стандарта, как обязательно надо, и как обязательно не надо, нет.
Re: include guards
От: Alexander G Украина  
Дата: 10.01.22 07:22
Оценка: +2
Здравствуйте, reversecode, Вы писали:

R>с изначальным


R>
R>#ifndef _file_hpp_
R>#define _file_hpp_
R>...
R>#endif
R>


R>и дополненными


R>
R>#ifndef _file_hpp_
R>#define _file_hpp_
R>#pragma once
R>...
R>#endif
R>


R>результаты не впечатлили


Компиляторы, которые оптимизируют #pragma once лучше, чем include guards, делают это тогда, когда #pragma once идёт первой, до неё только, возможно, комментарии и пустые строки.

Но вроде как сейчас компиляторов, оптимизирующих #pragma once лучше — нет. Ранее был таковым MSVC.
Русский военный корабль идёт ко дну!
Re[3]: include guards
От: sergii.p  
Дата: 10.01.22 07:33
Оценка:
Здравствуйте, reversecode, Вы писали:


М>>А что не так с прагма уанс, можно вкратце, и почему это секта?


R>/somedir1/header_file.h

R>/somedir2/header_file.h

R>два хидеры с разным содержанием но одинаковым именем

R>включенные в один модуль
R>считается что при прагма онце будут проблемы

так и стражи никак здесь не помогают

#ifndef _header_file_h
#define _header_file_h
...
#endif


есть вариант использовать GUID-ы вместо имён файлов. Там проблем будет поменьше, но и выглядит так себе.
Re[3]: include guards
От: YuriV  
Дата: 10.01.22 07:55
Оценка: +1
Здравствуйте, reversecode, Вы писали:


М>>А что не так с прагма уанс, можно вкратце, и почему это секта?


R>/somedir1/header_file.h

R>/somedir2/header_file.h

R>два хидеры с разным содержанием но одинаковым именем

R>включенные в один модуль
R>считается что при прагма онце будут проблемы

Нет, проблема как раз противоположная. Когда один и тот же файл лежит и включается из разных мест (да такое бывает в реальных проектах) и тогда в случае прагмы эти файлы будут считаться разными и естественно каждый раз включаться заново. А в твоём случае не поможет и ifndef header_file_h. При первом включении header_file.h в таблицу макросов препроцессора будет внесено значение header_file_h и последующие включения header_file.h будут скипнуты. В этом случае как раз и поможет прагма Так что если не знаешь структуры проекта более безопасно писать прагму, но если всё контролируешь, то, конечно, старый добрый ifndef. Единственный минус ifndef — он засирает таблицу макросов ненужной шелухой, но как ты показал сам удар по производительности компиляции незначителен, что в общем не удивительно.
Отредактировано 10.01.2022 8:04 YuriV . Предыдущая версия .
Re[4]: include guards
От: Михaил  
Дата: 10.01.22 08:08
Оценка:
Здравствуйте, YuriV, Вы писали:

YV>Нет, проблема как раз противоположная. Когда один и тот же файл лежит и включается из разных мест (да такое бывает в реальных проектах) и тогда в случае прагмы эти файлы будут считаться разными и естественно каждый раз включаться заново. А в твоём случае не поможет и ifdef имя_файла. При первом включении header_file.h в таблицу макросов препроцессора будет внесено значение header_file_h и следующие включение header_file.h будет скипнуто. В этом случае как раз и поможет прагма Так что если не знаешь структуры проекта более безопасно писать прагму, но если всё контролируешь, то конечно старый добрый ifdef. Единственный минус ifdef он засирает таблицу макросов ненужной шелухой, но как ты показал сам удар по производительности компиляции незначителен, что в общем не удивительно.


Ифдеф еще засирает заголовочные файлы лишними отвлекающими строками. Плюс, если вдруг вручную пишешь этот guard (что редко, но мало ли), можешь ошибиться в написании названия.
Вообще не понимаю, почему не сделали pragma once не на основании полного пути файла, а на основании имени файла и, например, хеша содержимого. Тогда уродливые ifdef ушли бы в прошлое.
Re[3]: include guards
От: удусекшл  
Дата: 10.01.22 09:17
Оценка: +3
Здравствуйте, Андрей Тарасевич, Вы писали:

М>>А что не так с прагма уанс, можно вкратце, и почему это секта?


АТ>Ну хотя бы то, что нет никакого "прагма уанс". Это не стандартная фича.


Но де факто она везде работает
Re[3]: include guards
От: удусекшл  
Дата: 10.01.22 09:17
Оценка: +5
Здравствуйте, reversecode, Вы писали:


R>считается что при прагма онце будут проблемы


Чушь какая
Re[5]: include guards
От: удусекшл  
Дата: 10.01.22 09:22
Оценка:
Здравствуйте, Михaил, Вы писали:

М
М>Ифдеф еще засирает заголовочные файлы лишними отвлекающими строками. Плюс, если вдруг вручную пишешь этот guard (что редко, но мало ли), можешь ошибиться в написании названия.
М>Вообще не понимаю, почему не сделали pragma once не на основании полного пути файла, а на основании имени файла и, например, хеша содержимого. Тогда уродливые ifdef ушли бы в прошлое.

Откуда дровишки?

Вики пишет:

...То есть, #pragma once применяется для тех же целей, что и include guard, но требует меньше кода и не допускает возможности коллизии имён.
...
Тем не менее, в релизе 3.4 GCC код обработки команды #pragma once был исправлен для корректной работы с символьными и жёсткими ссылками. Данная возможность была сочтена полезной и предупреждение было убрано.

Re[2]: Нужна ли защита от повторного включения
От: удусекшл  
Дата: 10.01.22 09:24
Оценка:
Здравствуйте, velkin, Вы писали:

R>>останусь на старом добром ifndef


V>Я тоже использую страж включения, но тут нужно сразу решить, или используешь только страж включения, или только pragma once.


Я использую и то и то одновременно. А в чем проблема?
Re[3]: Нужна ли защита от повторного включения
От: velkin Удмуртия http://blogs.rsdn.org/effective/
Дата: 10.01.22 09:30
Оценка:
Здравствуйте, удусекшл, Вы писали:

V>>Я тоже использую страж включения, но тут нужно сразу решить, или используешь только страж включения, или только pragma once.

У>Я использую и то и то одновременно. А в чем проблема?

В pragma once просто нет смысла, если стоит страж включения ifndef-define-endif. Я себя раньше спрашивал, а зачем я прописываю и то и другое. В итоге забил и оставил лишь страж включения. Но это было очень давно, тогда pragma once ещё не стала практически стандартом.
Re: include guards
От: andyp  
Дата: 10.01.22 10:13
Оценка: +8
Здравствуйте, reversecode, Вы писали:

R>останусь на старом добром ifndef


Съехал на прагму давно уже. Основные причины — копипаста гардов с одинаковыми именами и убитые при редактировании эндифы в хвосте файла.
Отредактировано 10.01.2022 10:14 andyp . Предыдущая версия .
Re[2]: include guards
От: reversecode google
Дата: 10.01.22 10:20
Оценка: -2
не однозначно
если судить по msvс шным стандартным хидерам, то да pragma once они делают перед include guard
если вчитываться в реддит или сорсы asio networking, то после

но под утро я решил сделать бранч и потестить и перед
по результатам, все равно разницы нет

если следовать логике, то once должна быть после guard
иначе можно промахнуться в случаях когда одно и тоже имя файла
присутствует в разных директориях ну и once будет как всегда впереди



как я сделал выводы выше топиками
из за того что я сам не плохо контроллирую что и куда я инклудю
и лишних включений у меня нет, то это никак не отразится

а вот на проектах где программисты потеряли уже инклуде флов
и инклудят лишних хидеров
им бы once оптимизации явно помогли
Re[3]: Нужна ли защита от повторного включения
От: B0FEE664  
Дата: 10.01.22 10:35
Оценка: -1
Здравствуйте, reversecode, Вы писали:

R>собственно мне pragma once был любопытен с точки зрения ускорения компиляции

С чего бы ему что-то ускорять?
Вот как надо:
#ifndef   ASDF_H
#include "asdf.h"
#endif

И каждый день — без права на ошибку...
Re[2]: include guards
От: Skorodum Россия  
Дата: 10.01.22 11:04
Оценка:
Здравствуйте, andyp, Вы писали:

A>Съехал на прагму давно уже. Основные причины — копипаста гардов с одинаковыми именами и убитые при редактировании эндифы в хвосте файла.

+ переиминование файла не требует дополнительных действий.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.