Category: it

Category was added automatically. Read all entries about "it".

bird

Безразличие к регистру - ошибка на миллиард долларов

Новая коллега осваивает работу с нашими продуктами. При этом у неё мак (целевая обстановка - Linux, полностью проверяется в виртуалке).
А у нас в репе в одном каталоге рядом registrar.cxx и Registrar.cxx.
Коротко:
1) head с явным указанием имени - показывает оба с разным содержимым.
2) ls пишет только один из них, Registrar.cxx.
3) "причем я клонила через XCode и в этой репе только с большой, а отдельно клонила через консоль и там только с маленькой"
"я хотела скопировать файл с маленькой буквы в папку где есть с большой, а он мне предложил его перезаписать"

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

Переименуем, конечно, но повод обсудить в общем случае.

Стандартные аргументы в пользу регистронезависимости: облегчение человекочитаемости. Это миф: её путают с человекоозвучиваемостью. Регистр не должен быть важен, например, в имени человека (хотя и тут могут быть тонкости). Но я не знаю, в каком случае с экрана будет читаться что-то в шрифтах, которые не различают регистр. И совсем не понимаю, почему и зачем различие регистра считается важнее, чем 100500 других различий.

Почему такие FS различают «foo.docx», «foo.docx », «foо.docx» и «fo​o.docx» (кто увидит разницу?), но не различают «foo.docx» и «Foo.docx»? И что будет в случае İı (см. Turkey test)?

Или вот:

> А у винды есть таблица преобразований для того что бы большие и маленькие буквы не отличались и как прнято в Микрософт в разных местах эта таблица может отличаться. В консоли файл создаётся, а explorer — переименовать файл не может, то кавычки не такие и файл не найжде, то пробелы в начале или конце файла и амба.

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

Но что за повышенный бред на маке?

This entry was originally posted at https://netch80.dreamwidth.org/51446.html. Please comment there using OpenID.
finch

вести с грабельных полей: bison, flex

Раз в пятый, наверно, пытаюсь сделать что-то лёгкое пробное на bison+flex и обламываюсь на чудовищно путаной и неудобной реализации. Прямой рукописный парсер оказалось сделать легче.
Вот сейчас что-то такое написал, что flex сгенерировал файл со строками:

#line 346 "lexer.h"
#undef yyIN_HEADER
#endif /* yyHEADER_H */
UFFER_STATE yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len ,yyscan_t yyscanner );


Кто такой UFFER_STATE и на ком он стоял?

(UPDATE: это получилось, если задать %option header-file, но не задать %option outfile. Но нигде не описано, что нельзя задавать только первый из них!)

bison не может в h-файле описать yylval. byacc не может описать в h-файле ничего, кроме кодов лексем - остальное, мол, описывайте сами.

Обоим bison и flex нельзя задать включаемые в этот h-файл строки, отчего, в частности, YYSTYPE или контекстный параметр парсеру надо или описывать одинаково в нескольких местах, или передавать void* и конвертить его в каждом месте использования. Причём они сами не включают нужное в выходные *.h, отчего их надо подключать только со своими источниками определений.

В доке flex сказано "читаем из yyin типа FILE*, вариантов нет", но чуть позже оказывается, что можно переопределить YY_INPUT. Извините, это была секция не туториала-букваря. Спасибо, что в нормальных stdio есть funopen() и fopencookie(), но кто кроме дедов об этом помнит?

Дефолтов для yywrap, yyerror не предлагается, хотя можно было уже давно придумать несколько типичных вариантов.

Bison с pure scanner передаёт параметр-куку всем функциям, кроме yylex(), которому она нужна больше остальных.

За один вечер можно наматериться на неделю.

UPD: победил. Но количество хаков, потребовавшихся, чтобы обойти недоработки и свернуть их с жесточайшего legacy, не радует.

This entry was originally posted at https://netch80.dreamwidth.org/47561.html. Please comment there using OpenID.
finch

дыбро

Немного IT-дыбра.

Обновил и подлатал представления о теме синтаксического анализа и вокруг. Общий вывод - всё достаточно грустно, разрыв теории с практикой достиг состояния "не сходятся, и всем пофиг". Все более-менее сложные реальные проекты творят нисходящий закат солнца вручную (Clang, Go...) или делают хитрые подпорки под относительно стандартные средства (как bison в GCC, но со специфичными C/C++ хаками, когда лексер смотрит в таблицы идентификаторов). Особенно "порадовало" Most vexing parse - после такого однозначно понятно, почему Go, Rust, Swift (и наверняка ещё много кто) взяли паскалевский порядок слов в определениях. (Напоминает конкуренцию SVO/SOV/etc. в живых языках и её последствия в виде позиции определяющего слова.) Или аналог для C# - когда парсинг конструкции вида f(G<1,2>(7)) зависит от достаточно "левых" признаков вроде следующих скобок.
При этом много голосов за "нематематичные" подходы вроде PEG (для которого фиг определишь в общем случае, написал конфликтную грамматику или нет - приоритеты и контекстные ограничения гарантируют разбор стандартных случаев, а там хоть трава не расти).

Обнаружил, что, несмотря на достаточно большой опыт в C/C++, не вляпывался до сих пор в самые мрачные варианты undefined behavior и его последствий, типа такого. И при этом никто не учит, что "here may be dragons" (целыми стадами) - например, Шилдт («C++ базовый курс») вообще ни слова, Страуструп - одно упоминание вскользь на 1000 страницах; в вузах тоже про это ни слова (по тому, как учили дочку); словно завеса умолчания, после которой вдруг встречаешься с последствиями, когда приступаешь к реальной работе. Как-то всё это странно. (Ещё ссылок, кому надо: 1, 2.)
Радует, что при всём при этом уже есть средства (как UB sanitizers) детекта заметного количества таких ситуаций (так что плотность их влияния на некорректность выходного результата становится ниже плотности влияния испорченной памяти).

Перевёл домашний настольник с FreeBSD на Linux. Причина - при переходе на 11ю фрю начало саморесетиться в произвольные моменты, но при реальной загрузке (два браузера) не жило больше 10 минут. На форуме не помогли, были только смутные обвинения видео в Haswell процессоре. Но умудрялось падать даже в Virtualbox, то есть видео ни при чём. Времени и настроения разбираться не было, так что привет, Kubuntu (такая же, как на работе и на лаптопе). Linux по крайней мере там работает :) но обидно. У фряхи было таки много мелких, но приятных удобств.

Осознал, что после превращения linkedin в обыкновенную соцсеть с лайками - присутствие на нём означает не только цель куда-то перейти, но и просто почитать что-то от коллег :) Для поддержки этой ситуации - начал закидывать такие же заметки на linkedin (на английском). Ну, начал - громко сказано :) но парочка есть ;)

This entry was originally posted at https://netch80.dreamwidth.org/47296.html. Please comment there using OpenID.
bird

Возврат нескольких значений

Интересно и немного забавно наблюдать, как новые языки программирования разворачиваются от старой кондовой концепции "функция может возвращать только одно значение".

C сохраняет подход с единственным значением. Где нужно возвращать более одного значения - начинается передача по указателю (примеры на каждом шагу).

В C++ уже можно за счёт tuple делать возврат с распаковкой в набор переменных, хотя реализация этого на уровне ABI скорее всего идёт через структуру в памяти, а не регистры. Ну и передача по ссылке, конечно же, как косвенный метод (с затратами памяти).

Pascal - та же передача по ссылке.

Forth изначально не имел этой проблемы (хотя держание всего на стеке - само по себе источник тормозов).

В Java формально одно значение (возврат объекта, пока нет value types, слишком дорог, хотя JIT это может соптимизировать). В результате возникают ситуации типа возврата массивов, или битовых трюков (которые работают только потому, что нету типов целых беззнаковых; заметим, что в этой доке везде пишут -1-x, а не ~x - почему?)

В C# вначале сделали out-параметры (и, я считаю, требование писать out и ref в списке параметров фактического вызова - гениальное и чрезвычайно важное требование; Паскаль до этого не дошёл), теперь наконец добавили кортежи.

Fortran за счёт требования передачи по ссылке или входного-выходного копирования всех параметров решал это изначально (считаем, что аналог ref из C#) и даже чрезмерно (вспомним тему модификации константы).

Динамические языки (типа Python, JS, Erlang) возвращают по-прежнему одно значение, но за счёт того, что оно может быть кортежом (списком...), получается произвольное количество (за счёт затрат на распаковку) - не решение, но лёгкий обход проблемы.

Go, Swift, Rust - возврат нескольких параметров сделан изначально.

Но на уровне скомпилированного кода приходится ориентироваться на монстров компиляции C, так LLVM сделал возможность возврата нескольких параметров, а GCC - нет. Он тормозит всех. В результате в свежайших разработках типа RISC-V ABI имеем только одно возвращаемое значение (может растягиваться на два регистра, сути это не меняет). Не могу нагуглить, что мешает GCCʼшникам.

This entry was originally posted at http://netch80.dreamwidth.org/45373.html. Please comment there using OpenID.
bird

ssh с ключом и паролем от сервера?

Хочется странного. При стандартной авторизации ssh по ключу есть кодовая фраза на стороне клиента. При этом он может менять её, отдавать ключ другому, контроль доступа слабоэффективен (по ip не годится, если ip может меняться)...
Вот если бы ключ принимался, но при этом сервер требовал дополнительный пароль. После успешного входа - попадает в полноправного пользователя (но, если не знает основной пароль пользователя, не может управлять доступом).
Для самого ssh можно к ключу добавить forced command (типа "ask-password foo"), но дальше пароль должен попросить кто-то другой. Причём желательно, чтобы управление доступом тут (какие есть дополнительные пароли (названия - ключи к словарю) и сами пароли) было доступно пользователю не по умолчанию, а через свой основной пароль.

Один вариант реализации понятен - вход в дополнительного системного пользователя, который имеет право sudo su в основного. Но это очень громоздко и требует странных подпорок. А более прямо?

Я бы накостылял что-то в духе:

1. /var/lib/add_pass/$user/$key - хэш пароля
2. /usr/lib/add_pass/check $key - forced command для ключа, проверяет пароль, для доступа к п.1 требует suid или лучше sgid.
3. /usr/lib/add_pass/control - средство управления - тоже шлюз привилегий.

Как защитить authorized_keys?

Или убедите, что это всё бесполезно, если вообще кого-то пускаем шеллом :)

This entry was originally posted at http://netch80.dreamwidth.org/44032.html. Please comment there using OpenID.
bird

Рабочий вечер, пляски вокруг kdb

Обычный рабочий вечер, переписка в slack после того, как некий запрос завесил сервер так, что Ctrl+C из локальной консоли не помогло.

user1: почему запрос `select count time/5 from sesslog` убил кдб сервер?
user2: http://code.kx.com/wiki/Reference/Slash
user3: я подозреваю что user1 хотел разделить на 5))
user2: 1. приоритет операций строго справа налево. если нет скобок
user2: 2. для деления используется %, а не /
user2: Или div если целочисленное
user1: почему убилось kdb
user2: 3. если нужно считать кол-во записей, используйте i вместо имени столбца.
VN: user2, ты как на русском форуме - отвечаешь на что угодно, кроме исходного вопроса
user2: Валик, я ткнул носом в доку
VN: user2 блин. Можешь объяснить, при чём тут over к глобальному заклину процесса?
user1: хорошо.
user1: что из этого http://code.kx.com/wiki/Reference/Slash
user1: и почему
user3: потому что твой овер рекурсивно выжрал всю доступную память процессу
VN: неправда.
VN: я вот тут воспроизвожу - память не меняется, хотя процесс жрёт 100%
user2: over: The iteration form of / terminates when either: (1) two successive results agree within comparison tolerance or (2) the result matches the initial input. The latter will save you from some infinite cycles but not all
user2: converge: When / is following a monadic function f/[g;x] will apply f to x until g returns 0b
VN: user2, ты программист. Я это понял.
guru4: а вы смотрели, во что он скомпилился? на K
guru4: (,`x)!,((/;`time);#:;5)
guru5: а ну да, теперь все понятно
(под репликой чужой смайл типа "слёзы из глаз от смеха")
user1: и это зацикливает инстанс?
guru4: да
user1: и какое поведение будет если добавить нитей?
user1: как, кроме как административно, избежать отказа в обслуживании
guru5: а в нашем интерпретаторе подсчет инструкций и всегда отдается yield в интерпретатор :)
guru4: это вежливый, хороший интерпретатор
guru4: а К просто крутит цикл

Картинка в тему.


This entry was originally posted at http://netch80.dreamwidth.org/43544.html. Please comment there using OpenID.
bird

wrike suxx!

У нас тут в качестве трекера wrike используется, так вот что я вам имею сказать: я такого аццкого, феерического дерьма не видел вообще. (Почти) любая другая система, даже богом проклятая JIRA, будет лучше.
Причём засада не в формальных возможностях, а в деталях реализации. Всё, что можно было сделать через зад, сделано именно через зад, причём ещё и с приподвывертом.
А ещё она страшно тормозит.

UPD: а рекламная джинса от Blogeratorʼа особенно позорна.
bird

UB reasoning (копия)

Дискуссия прошла в Fido, пересмотрел - думаю, стоит сделать копию в чём-то индексируемом.

Collapse )
Смотря на более поздние языки (от Java и вплоть до Go, Rust и прочих) - там все описанные проблемы „урезают“ - видимо, считают неподъёмным основной массе?
bird

О вводе-выводе, скорость и корректность

Дочка сдаёт задачи по программированию, как это сейчас модно, через e-judge и аналогичные системы.

Первая задача: много вывода. Лимит времени работы в системе - 100 мс. На моём десктопе показывает 45 мс. Вывод через cout << val. Вспоминаю рассказы про тормознутость iostreams, подсказываю про stdio. Переписывает, сдаёт. Локально время сократилось до 2 мс. В целевой системе - прошло.

Вторая задача: очень много ввода (максимум теоретически возможного по условиям - 20 миллионов intʼов). fscanf даёт 1.2 секунды. Ручная замена на враппер вокруг getc() - ~0.2 секунды. Лимит в системе тот же - 100мс. Всё равно много. Вытаскивает вчерашний вариант на Паскале, исправляет ошибки, отправляет. Проходит. Сравниваю время после локального freepascal. 3 миллисекунды(!)

Сначала я подумал, что случилось чудо и паскалевцы сумели оптимизировать до предела. Но решил посмотреть внимательнее. Когда ktrace показывает, что из файла на 10M целых читается только 256 байт... мягко говоря, странно. Пропущу пляски с бубном, но результат раскопок: во FreePascal двухбайтный integer. Соответственно, 10000000 превратилось на чтении обычным read(n) в... -27008. Последующий цикл чтения for i:=1 to n тупо выполнился ноль раз. А тесты как раз сошлись так, чтобы повторить эту ошибку.
Посмотрел, что там longint - 4 байта, заменил все integer на него. Время работы на те же 20M целых поднялось до 1.7 секунды. Что ж, отсутствие чуда уже доказано.

Вот как можно на таких допотопных средствах детей учить?
bird

protocol-design-treatise-ru

Выложил на гитхаб свой трактат о протоколах и форматах (начатый ещё в LN, до сих пор представленный только на собственном сайте). Не в последнюю очередь из-за того, что на гитхабе другим удобнее следить за изменениями:)
Перевод на английский - будет по мере поступления времени и вдохновения.