- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
// где-то в коде нашлось
PRIVATE IdxArray* idx_array_append_val_dyn(IdxArray* arr, PlmIndex idx)
// private.h
#ifdef PLM_TEST
#define PRIVATE extern
#else
#define PRIVATE static
#endif
Нашли или выдавили из себя код, который нельзя назвать нормальным, на который без улыбки не взглянешь? Не торопитесь его удалять или рефакторить, — запостите его на говнокод.ру, посмеёмся вместе!
+135
// где-то в коде нашлось
PRIVATE IdxArray* idx_array_append_val_dyn(IdxArray* arr, PlmIndex idx)
// private.h
#ifdef PLM_TEST
#define PRIVATE extern
#else
#define PRIVATE static
#endif
внезапно...
Ну вот разве что такое извращение: Но здесь мы теряем возможность проинициализировать переменную в сишке с реализацией.
Это чтобы увеличить шанс получить UB из-за нарушения ODR? Прохладная стори.
P.P.S. А в стандарте сишки вообще такого правила походу нет.
Ну для не инлайн функций никаких проблем с диагностикой быть не может. Неважно что там конфликтует в телах функций, линкеру достаточно сказать, что он видит две функции с одним именем (в случае крестов - с одинаковой сигнатурой).
В С89, емнип, инлайнов вообще нет, поэтому и проблем нет, обсуждать можно только конкретные компиляторы.
С99 статик инлайн никаких проблем вызвать не может, потому что он статик и наружу не торчит.
Остаются крестоинлайны и не статик инлайны в С99. В крестах диагностику выдать очень сложно - линкеру пришлось бы сравнивать тела функций. В с99 extern inline может быть только один, но может не совпасть с inline версией в текущей единице сборки, а какую из них выберет компилятор - никто кроме него не знает (кстати походу именно по этой причине в не static inline с99 запрещает static переменные).
Отсюда вывод: единственный случай, когда мы в полной жопе и диагностику запилить очень сложно - если не статическая инлайн функция имеет разное тело в разных сборочных единицах. Но тот, кто так пишет - ССЗБ.
P.S. Я не думаю, что PRIVATE из топика стали бы привинчивать к инлайнам, поэтому там все норм.
Но! Нарушить одр можно и от класса к классу (а не только в функциях). Так что мест для нарушений хоть залейся.
Вон по новому стандарту наличие private в классе или его отсутствие (там подругому сформулировано, но в контексте обсуждения не важно) меняет результат std::is_standart_layout.
Это к вопросу о #define private public в модулях, подключаемых для unit testов, чтобы протестировать приватные члены (и такое взбредает в голову некоторым).
За счет нарушения ОДР класса у нас сьезжает какая-нибудь функция из-за разного значения std::is_standart_layout в разных модулях в при использовании в этой функции. Нарушения одр вызывают целые цепочки нарушений одр (реальное УБ).
Это тут нам ещё повезло. Некоторыми компиляторами обнаруживается, но если нет, то гораздо хуже вылезают порчи памяти из-за нарушения одр в классе по одному из членов, например в одном из модулей в классе члена нет или он друго го типа.
> например в одном из модулей в классе члена нет или он другого типа.
> порчи памяти из-за нарушения одр в классе по одному из членов
> Нарушить одр можно и от класса к классу...
...запилив два одноименных класса в разных сборочных единицах, либо из-за рассогласования дефайнов/прагм между сборочными единицами. В обоих случаях - ССЗБ. Хотя случайно вполне можно нарваться, не спорю.
Очень жаль, что крестокомпиляторы поголовно юзают классические сишные линкеры, нихера не понимающие в крестах, и не имеющие ни малейшего понятия о классах. Если бы компилятор мог поместить немного инфы о классах в особую секцию в объектнике, а линкер просто бы сверял эту метаинфу, и ругался, если класс называется одинаково, а метаинфа разная - проблемы бы не было. Да и время компиляции от этого бы не выросло...
P.S. Друг ловил подобную проблему с ODR - сгенерил кутикреаторским мастером заготовку для плагина, а ашки-заглушки с пустыми классами удалить забыл. В итоге плагин собрался с пустым классом (т.к. инклудил он через "" а не через <>), а в сошке был полноценный. new в плагине выделяло намного меньше памяти, конструктор вызывался из сошки, последствия можно себе представить.
P.P.S. Проблему локализовали valgrind'ом, т.к. про лишнюю ашку никто даже не подумал.
*Не было бы проблемы с рассогласованием раскладки полей класса и списка его методов. Проблема с телами методов осталась бы, т.к. адекватного способа их сравнения нет.
ушло бы такое понятие, как почти одинаковый инлайн метод, так как ушло бы такое понятие как дубликат инлайн метода (или класса) из-за отсутствия хедеров в новых проектах.
Тем, что инклуд <> - это для файлов с шаблонами?
Визуал Студия все или почти все вышеназванные подключения понимает правильно и подключает, но не думаю, что это по стандарту.
Ну и я всегда считал, что <kokoProject.h> для случаев если путь указан в мейкфайле\файле проекта, а "//kokoko//kokoProject.h", если путь указан прямо в коде абсолютный или относительно того, что указан в мейкфайле\файле проекта.
Вообщем я не знаю. Но ждем тех, кто стандарт чтил.
В gcc <> ищет в директориях, указанных в -I, затем в системных, а "" ищет относительно текущего файла, а затем там же где и <>.
В вижуалке, емнип, точно так же, но "" после директории текущего файла смотрит еще и в директорию того файла, который его заинклудил и так далее до самого верха, и только затем переходит к /I.
Краткое резюме - в 99% случаев ашки из своего проекта подключают через "", а из внешних библиотек через <>.
А boost внешняя, но "boost\\smart_ptr\\shared_ptr.hpp"
#respect
я вообще не понял, что он хотел сказать
#respect за #respect
p.s. а вообще, может я и @LispGovno одно лицо
"буст внешняя, но у меня работает только так" - засунул буст как подпапку своего проекта?
"буст внешняя, но в сорцах буста используется вот так" - пиздёж, там прямые слеши, но в инклюдах собственного же говна "" использовать правильно
"буст внешняя, но я вовсе не это хотел сказать" - ближе всего
кто тут ещё в кандидаты на LispGovno крайний?
...
А на ликеро-водочный нет?.
Ну я же написал: "" ищет в implementation defined месте, а потом там же где <>. Т.е. все, что нашло бы <> найдет и "".
P.S. Нахуя писать \\ вместо /? Смотрится уёбищно, а все компиляторы вроде бы / понимают.
P.P.S. Да и, если мне изменяет память (в данном случае не уверен), по стандарту экраны в инклудах не пашут.
виндузятники, сэр
P.S. фф предлагает заменить "виндузятники"на взяточники
Это плагин Навального шалит. Жулики и воры.
Сишка99: [i]f the characters ', \, ", //, or /* occur in the sequence between the < and > delimiters, the behavior is undefined. Similarly, if the characters ', \ , //, or /* occur in the sequence between the " delimiters, the behavior is undefined.
Так что \\ мало того, что уёищно смотрится, так оно еще и UB ;)
Юзай портабельный* / и будет тебе счастье.
*в стандарте не описано, как задавать путь к подпапкам, но / работает во всех известных мне компиляторах.
либа, состоящая из нескольких .h + .c файлов
для собственной отладки можно было и как есть
но т.к. надо было отдавать сторонней организации в хитрожопом объектном + бинарном виде, в целях сокрытия внутренней реализации переделал под static + инклюдил .c файлы напрямую в центральный .c (экспортируя наружу только несколько имен)
к слову, второй вариант всё равно не прокатил, т.к. получающийся с помощью убогого gcc 2.7.х объектник .o, как бы я не изголялся, содержал все внутренние элементы, доступные поименно (они просто были помечены, как local - "t", но тем не менее, это было самое настоящее палево)
так что пришлось все стасики (функции и константные массивы) вручную переинлайнить в местах вызова и получить отличный дуршлаг с вермишелью
а так, по старой памяти в ld были какие-то ключики, но я так же видел еще какую-то черную магию в прошлом с objcopy.
ЗЫ gcc 2.7? в музее работаешь? :)
я не виноват
такой вот у стороннего партнера оказался особенный тулчейн для их производственной линии, и ничего с этим было не поделать