Pull to refresh
59
1.4

Пользователь

Send message
Похоже, что тс укурился колесами. :)
Правда, некоторые связи будут весьма странными с точки зрения логики обывателя. Но это не исключает их невозможности.
Отличная статья, чисто в теоретическом смысле — уже по объему «введения» дает понять, что это не так просто, как кажется. :)

В примере с горизонтальным сдвигом «Слайд-шоу без разбивки на страницы» будут проблемы с производительностью (чем больше слайдов, тем будет больше тормозить). overflow: hidden для «окна» и гигантской «лентой» внутри, float: left — все это ацкий ад. Для того, чтобы обеспечить константную производительность, надо использовать абсолютное позиционирование.

В примере «Навигация с клавиатуры» не поддерживается фокус — если на странице несколько аналогичных слайдеров, будут перелистываться все. Нет отвязки событий от 'body' для корректного удаления слайдера.

В крайнем примере «JavaScript: использование внешнего API» при клике в слайд запускается видео не на текущем слайде, а на последнем. В общем случае трюк с «opacity: 0» не работает.

Это лишь часть того, что видно сходу. Статья может быть полезна для начинающих «потренировацца», но не как инструкция для сборки промышленного решения по шагам. На практике слайдеры собирают совсем не так.
Похоже, что отправлять жалобы в Google со списками урлов, собранными по ключевым словам, становится популярной практикой. Недавно несколько проектов на GitHub получали уведомления за созвучность с каким-то проном.
Если так дело и дальше будет так развиваться, то использование ЧПУ скоро станет антипаттерном в SEO'шных практиках.
Вот пример на понимание:

int* b = (int *)NULL;
int* c = &*b;
*c;


Определено-ли «c» при объявлении во второй строчке? Да ( &*E is equivalent to E (even if E is a null pointer)).
Будет-ли в третьей строке UB при попытке разыменовать *c? Да (по правилу на которое вы ссылаетесь).

В примере «struct usb_line6 *line6 = &podhd->line6;» вычисляется указатель на line6, т.е. смещение line6 относительно podhd. Смещения не зависят от значений, только от типов. Тут нет разыменовавания, и пункт на который вы ссылаетесь не подходит. Поэтому я о нем не говорил (а не вырвал из контекста, как вы выразились).

Я мог бы с вами согласиться на 100%, если бы все четыре основных компилятора не были бы C/C++.

Вы на 100% не сможете скомпилировать программу на «C/С++»: это будет программа либо на «С», либо на «С++».
Вопрос решается статусами. На эту тему есть хорошая статья про кофе и старбакс.
Тут с первой строчки было понятно, что топик обречен на успех.
Ненароком я породил большую дискуссию, касающуюся того, допустимо ли использовать в Си/Си++ выражение &P->m_foo,

Это неизбежно, когда ненароком ставят рядом два довольно-таки разных языка (более эпичный вариант лишь Java/JavaScript). ;)

Но эту ветку комментов конкретизировал dimoclus:
Я ни в коем случае не лезу в язык C++ — у него свой стандарт, гораздо более сложный и объемный.

Поэтому я тоже говорю про С. В стандартах «С» нет понятий ни виртуального наследования, ни перегрузки операторов. Это ведь не значит, что они, а так же все, что сними может быть связано, автоматически становятся UB? — это значит, что С совсем другой язык, это не С++.

Для С вопрос разъясняется в:
102) Thus, &*E is equivalent to E (even if E is a null pointer), and &(E1[E2]) to ((E1)+(E2)). It is always true that if E is a function designator or an lvalue that is a valid operand of the unary & operator, *&E is a function designator or an lvalue equal to E. If *P is an lvalue and T is the name of an object pointer type, *(T)P is an lvalue that has a type compatible with that to which T points.

Отсюда напрямую следует вывод, что если компилятор С вздумает разыменовывать указатели при интерпретации выражения, то свойство эквивалентности будет нарушено (как раз для случая null pointer, который тут особо отмечен, ибо в процессе он словит UB). Поэтому так делать нельзя. Поэтому нормальный компилятор С так делать не будет и с точки зрения программиста на С тут нет UB.

Мне кажется, что рационализм в проблеме, поднятой Andrey2008 есть. Делать прямые указатели на чужие внутренности может быть чревато по многим причинам. Поэтом интерес к вопросу, как разработчика статического анализатора, понятен. Просто вопрос этот скорее из области best practices программирования, а не спецификаций С.
Таким образом здесь мы соглашаемся, что podhd!=nullptr

Возражаю! :) В общем случае такая эвристика не уместна, у Andrey2008 про это было:
А есть ли какая-та ситуация, когда при P == nullptr мы напишем &P->m_foo и всё будет хорошо? Да, например это может быть аргументом оператора sizeof: sizeof(&P->m_foo).

Тут нельзя делать заключение о значении указателя на основе лишь синтаксиса, поскольку нет разыменовывания — интерпретация выражения не выходит за рамки арифметики указателей.
Вы правильно пишите, только это другой пример. =)

В топике не *x, а &*x, и как написали выше нет разыменовывания, а лишь простая арифметика с указателями:
Thus, &*E is equivalent to E (even if E is a null pointer)

Например, такой код:
 struct usb_line6_podhd *podhd;

Обычное объявление указателя, значение указателя не определено. Возникает-ли здесь UB и надо-ли бить тревогу? Думаю, что нет. С точки зрения поведения компилятора/стандартов ситуация решается однозначно. С точки зрения поведения программы — зависит о того, как этот указатель будет использоваться дальше (чтобы вынести вердикт, нужно анализировать остальной код).

Возьмем другой пример:
int foo(int a)
{
   int b = a + 100500;


Обычное сложение. Возникает-ли здесь UB, и нужно-ли бить тревогу? С точки зрения стандарта/компилятора все однозначно — какое-то значение у входного параметра будет. С точки зрения программы — зависит от значения на входе. Если прилетит значение в районе INT_MAX, будет переполнение. Является-ли такой код проблемным? Чтобы вынести вердикт нужно анализировать остальной код. Возможно тут есть место для логической ошибки, и стоит добавить проверку на граничные значения входного параметра. В общем, это нормальная программисткая ситуация, когда нужно определяться с логикой проверки входных данных, а не UB.

Теперь смотрим пример из топика:
static int podhd_try_init(struct usb_interface *interface,
        struct usb_line6_podhd *podhd)
{
struct usb_line6 *line6 = &podhd->line6;

Если-по простому, здесь записано выражение «к podhd прибавить смещение line6 в структуре usb_interface». Т.е. не смотря на количество закорючек, тут записана такая же простая арифметика, как во втором примере. Только это арифметика с указателями. Ни какого разыменовыания здесь нет (тут уже неоднократно про это писали, в т.ч. вы сами цитатой эксперта). Можно-ли говорить тогда про UB? С точки зрения стандартов/компилятора выражение интерпретируется однозначно, поэтому UB нет. С точки зрения логики программы — зависит от значения указателя, которое прилетит на вход функции. Может прилететь правда адрес структуры, может NULL, а может какой-то бред (если передадут неинициализированный указатель, как в первом примере). Но в «С» не запрещается хранить в указателях «непонятно что» (см. первый пример). Тут может иметь место логическая ошибка (случай когда нужна проверка входных параметров функции), но само по себе это не UB.
Причиной холивара часто является недооценка основных качеств процедурного программирования и ООП. Не всякий «код с классами», это обязательно ООП.

Процедурный код хорошо себя проявляет на ранних этапах разработки, т.к. на него удобно ложатся привычные подходы алгоритмического моделирования, и первые видимые результаты появляются очень быстро. Основные проблемы таких программ: низкая абстрактность и сильная связанность (так называемый «спагетти-код»). Это приводит к тому, что ранее написанный код сложно переиспользовать, а эффекты, возникающие при изменении требований и модификации кода, могут непредсказуемо распространяться по всей программе. Поэтому развивать и поддерживать такой код — нервно и дорого.

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

Поскольку время эксплуатации и развития софта обычно в десятки раз превышает время его начальной разработки, то использование ООП, в целом дает ощутимую выгоду. Собственно, за это и не любят «процедурщину» в ООП архитектуре — она несет за собой весь ворох характерных для процедурного подхода проблем, помноженный на архитектурные заморочки (так называемый «равиоли»-код), — что приводит в итоге к сильному росту затрат на поддержку.
Почему-то, ни один из них не отрабатывает ситуацию, когда у окна браузера появляется горизонтальный скролл (на демках хорошо видно несуразность, достаточно сузить окно по горизонтали). Все сильно по-разному, когда динамически меняется ширина контейнера. Ужас с позиционированием на мобильных девайсах.
увы
увидел ссылки фиолетовыми.
Или полноценная реализация полифилла для position: sticky это какой-то прямо вызов — найдется кто смелый? :)
В IE с уязвимостями в последнее время стало хорошо. Их немного больше, чем в других браузерах по причине того, что его разработка ведется гораздо активнее.

Если мерить, по-вашему, — активность разработки количеством багов, — выходит, что раньше они пилили IE круглосуточно. :)
Интересно, как в библиотеках вообще хранятся электронные версии? Ведь электронную версию, в стеллаж не поставить как книжку, а хранить информацию, наверняка, надо так же долго и надежно. Каковы объемы данных, которые должна хранить библиотека? Используются-ли какие-то типовые решения для хранения в плане инфраструктуры, софта или каждая библиотека придумывает что-то свое?
Возможно, смысл не в построении единого видеоряда, как при монтаже, а в возможности взглянуть на происходящее с разных позиций. Возможно, в такой компоновке они смогут представлять видео, снятое разными пользователями на одном мероприятии.
<meta http-equiv=«X-UA-Interoperable» content=«IE=EmulateIE7» />
Хотя ansible и fig/docker решают похожие задачи, решают они их принципиально по-разному.
Ansible это универсальная штука, чтобы приводить состояние машинок в требуемое, для вашего приложения, путем дергания их внутренностей с помощью абстрактных правил по ssh. Docker собирает контейнеры «с нуля», упаковывая операционку вместе с приложением. Поэтому степень контроля тут в разы выше и есть возможности для различных оптимизаций. В целом, деплой через ansible занимает минуты, в то время как docker все делает за секунды.
docker с каждой версией становится проще и обновляется чаще, чем убунта. поэтому есть смысл подключить их репозиторий docs.docker.com/installation/ubuntulinux/#docker-maintained-package-installation
Автор сильно переусердствовал с модульностью, в приложении практически нечего нет, а файлов и модулей уже...

Кстати, на ангуляре часто так и пишут: один файл — одна сущность. Это снимает часть вопросов, связанных с поддержкой кода, его тестируемостью и повторным использованием. Например, недавно была статья habrahabr.ru/post/243565/. У автора тоже что-то подобное, только все вручную. Все-таки JS менее выразительный язык, чем питон, потому код имеет тенденцию скатываться в состояние неподдерживаемого «говнокода» быстрее. Отсюда, приходится строже относится к таким вещам, как модульность.

Так же считаю излишним выносить js в отдельный шаблон и потом его подключать. В оригинале автор использует для этого templates/javascripts.html.

Мы в коммерческой разработке используем не только bower, но и много — gulp для «компиляции» статики, пост-процесснига django-шаблонов, и т.п… С одной стороны, тащить в проект уровня «hello world!» инфраструктуру кажется перебором, но с другой — к хорошему быстро привыкаешь, так что потом сложно отказываться. :) Могу предположить, что в реальных проектах у них больше одного django-шаблона, куда подключается один и тот же набор скриптов. Отсюда такое решение.
По части сети проблем нет. Все-таки по сети передаются байты, а не строки. Строки получаются лишь после интерпретации этих данных программой. Они лишь частный случай. С тем же успехом может прилететь половина байтового представления Int. Порядок интерпретации всегда на совести программы.

Information

Rating
1,463-rd
Location
Екатеринбург, Свердловская обл., Россия
Date of birth
Registered
Activity