- 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
внезапно...
bormand 26.02.2013 10:45 # +2
Ccik 26.02.2013 10:56 # 0
absolut 26.02.2013 11:25 # +2
bormand 26.02.2013 12:26 # 0
Ну вот разве что такое извращение: Но здесь мы теряем возможность проинициализировать переменную в сишке с реализацией.
LispGovno 27.02.2013 16:09 # 0
Это чтобы увеличить шанс получить UB из-за нарушения ODR? Прохладная стори.
bormand 27.02.2013 20:50 # +1
bormand 27.02.2013 20:59 # +2
P.P.S. А в стандарте сишки вообще такого правила походу нет.
LispGovno 27.02.2013 21:17 # +1
bormand 27.02.2013 22:30 # +2
Ну для не инлайн функций никаких проблем с диагностикой быть не может. Неважно что там конфликтует в телах функций, линкеру достаточно сказать, что он видит две функции с одним именем (в случае крестов - с одинаковой сигнатурой).
В С89, емнип, инлайнов вообще нет, поэтому и проблем нет, обсуждать можно только конкретные компиляторы.
С99 статик инлайн никаких проблем вызвать не может, потому что он статик и наружу не торчит.
Остаются крестоинлайны и не статик инлайны в С99. В крестах диагностику выдать очень сложно - линкеру пришлось бы сравнивать тела функций. В с99 extern inline может быть только один, но может не совпасть с inline версией в текущей единице сборки, а какую из них выберет компилятор - никто кроме него не знает (кстати походу именно по этой причине в не static inline с99 запрещает static переменные).
Отсюда вывод: единственный случай, когда мы в полной жопе и диагностику запилить очень сложно - если не статическая инлайн функция имеет разное тело в разных сборочных единицах. Но тот, кто так пишет - ССЗБ.
P.S. Я не думаю, что PRIVATE из топика стали бы привинчивать к инлайнам, поэтому там все норм.
LispGovno 27.02.2013 23:07 # +1
Но! Нарушить одр можно и от класса к классу (а не только в функциях). Так что мест для нарушений хоть залейся.
Вон по новому стандарту наличие private в классе или его отсутствие (там подругому сформулировано, но в контексте обсуждения не важно) меняет результат std::is_standart_layout.
Это к вопросу о #define private public в модулях, подключаемых для unit testов, чтобы протестировать приватные члены (и такое взбредает в голову некоторым).
За счет нарушения ОДР класса у нас сьезжает какая-нибудь функция из-за разного значения std::is_standart_layout в разных модулях в при использовании в этой функции. Нарушения одр вызывают целые цепочки нарушений одр (реальное УБ).
Это тут нам ещё повезло. Некоторыми компиляторами обнаруживается, но если нет, то гораздо хуже вылезают порчи памяти из-за нарушения одр в классе по одному из членов, например в одном из модулей в классе члена нет или он друго го типа.
bormand 28.02.2013 00:55 # +1
> например в одном из модулей в классе члена нет или он другого типа.
> порчи памяти из-за нарушения одр в классе по одному из членов
> Нарушить одр можно и от класса к классу...
...запилив два одноименных класса в разных сборочных единицах, либо из-за рассогласования дефайнов/прагм между сборочными единицами. В обоих случаях - ССЗБ. Хотя случайно вполне можно нарваться, не спорю.
Очень жаль, что крестокомпиляторы поголовно юзают классические сишные линкеры, нихера не понимающие в крестах, и не имеющие ни малейшего понятия о классах. Если бы компилятор мог поместить немного инфы о классах в особую секцию в объектнике, а линкер просто бы сверял эту метаинфу, и ругался, если класс называется одинаково, а метаинфа разная - проблемы бы не было. Да и время компиляции от этого бы не выросло...
P.S. Друг ловил подобную проблему с ODR - сгенерил кутикреаторским мастером заготовку для плагина, а ашки-заглушки с пустыми классами удалить забыл. В итоге плагин собрался с пустым классом (т.к. инклудил он через "" а не через <>), а в сошке был полноценный. new в плагине выделяло намного меньше памяти, конструктор вызывался из сошки, последствия можно себе представить.
P.P.S. Проблему локализовали valgrind'ом, т.к. про лишнюю ашку никто даже не подумал.
bormand 28.02.2013 05:29 # 0
*Не было бы проблемы с рассогласованием раскладки полей класса и списка его методов. Проблема с телами методов осталась бы, т.к. адекватного способа их сравнения нет.
LispGovno 28.02.2013 06:40 # 0
ушло бы такое понятие, как почти одинаковый инлайн метод, так как ушло бы такое понятие как дубликат инлайн метода (или класса) из-за отсутствия хедеров в новых проектах.
TarasB 28.02.2013 10:26 # +2
Тем, что инклуд <> - это для файлов с шаблонами?
LispGovno 28.02.2013 11:22 # −2
Визуал Студия все или почти все вышеназванные подключения понимает правильно и подключает, но не думаю, что это по стандарту.
Ну и я всегда считал, что <kokoProject.h> для случаев если путь указан в мейкфайле\файле проекта, а "//kokoko//kokoProject.h", если путь указан прямо в коде абсолютный или относительно того, что указан в мейкфайле\файле проекта.
Вообщем я не знаю. Но ждем тех, кто стандарт чтил.
bormand 28.02.2013 12:06 # +1
В gcc <> ищет в директориях, указанных в -I, затем в системных, а "" ищет относительно текущего файла, а затем там же где и <>.
В вижуалке, емнип, точно так же, но "" после директории текущего файла смотрит еще и в директорию того файла, который его заинклудил и так далее до самого верха, и только затем переходит к /I.
Краткое резюме - в 99% случаев ашки из своего проекта подключают через "", а из внешних библиотек через <>.
LispGovno 28.02.2013 12:59 # −1
А boost внешняя, но "boost\\smart_ptr\\shared_ptr.hpp"
absolut 28.02.2013 13:18 # +3
defecate-plusplus 28.02.2013 13:22 # +3
#respect
я вообще не понял, что он хотел сказать
absolut 28.02.2013 14:44 # +4
#respect за #respect
p.s. а вообще, может я и @LispGovno одно лицо
defecate-plusplus 28.02.2013 15:01 # +3
"буст внешняя, но у меня работает только так" - засунул буст как подпапку своего проекта?
"буст внешняя, но в сорцах буста используется вот так" - пиздёж, там прямые слеши, но в инклюдах собственного же говна "" использовать правильно
"буст внешняя, но я вовсе не это хотел сказать" - ближе всего
bormand 28.02.2013 15:12 # +5
absolut 28.02.2013 15:53 # +2
кто тут ещё в кандидаты на LispGovno крайний?
LispGovno 28.02.2013 16:40 # 0
...
А на ликеро-водочный нет?.
TarasB 28.02.2013 18:32 # −3
bormand 28.02.2013 13:32 # +2
Ну я же написал: "" ищет в implementation defined месте, а потом там же где <>. Т.е. все, что нашло бы <> найдет и "".
P.S. Нахуя писать \\ вместо /? Смотрится уёбищно, а все компиляторы вроде бы / понимают.
P.P.S. Да и, если мне изменяет память (в данном случае не уверен), по стандарту экраны в инклудах не пашут.
govnomonad 01.03.2013 05:52 # +2
виндузятники, сэр
P.S. фф предлагает заменить "виндузятники"на взяточники
bormand 01.03.2013 06:04 # +4
LispGovno 01.03.2013 06:45 # +1
absolut 01.03.2013 07:06 # +4
Это плагин Навального шалит. Жулики и воры.
bormand 28.02.2013 13:57 # +3
Сишка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 ;)
Юзай портабельный* / и будет тебе счастье.
*в стандарте не описано, как задавать путь к подпапкам, но / работает во всех известных мне компиляторах.
defecate-plusplus 27.02.2013 11:42 # +2
либа, состоящая из нескольких .h + .c файлов
для собственной отладки можно было и как есть
но т.к. надо было отдавать сторонней организации в хитрожопом объектном + бинарном виде, в целях сокрытия внутренней реализации переделал под static + инклюдил .c файлы напрямую в центральный .c (экспортируя наружу только несколько имен)
к слову, второй вариант всё равно не прокатил, т.к. получающийся с помощью убогого gcc 2.7.х объектник .o, как бы я не изголялся, содержал все внутренние элементы, доступные поименно (они просто были помечены, как local - "t", но тем не менее, это было самое настоящее палево)
так что пришлось все стасики (функции и константные массивы) вручную переинлайнить в местах вызова и получить отличный дуршлаг с вермишелью
Dummy00001 27.02.2013 19:55 # +2
а так, по старой памяти в ld были какие-то ключики, но я так же видел еще какую-то черную магию в прошлом с objcopy.
ЗЫ gcc 2.7? в музее работаешь? :)
defecate-plusplus 27.02.2013 20:23 # +2
я не виноват
такой вот у стороннего партнера оказался особенный тулчейн для их производственной линии, и ничего с этим было не поделать