LINUX.ORG.RU
ФорумTalks

Сишная галера

 


0

4

Представьте, что вам надо запрограммировать девайс на языке С. Девайс проприетарный чуть более, чем полностью. Какая там ОС - неизвестно. Есть только куций API, с кастомными функциями для выделения памяти в куче и проч.

Вам надо в конечном счёте читать и разбирать блобы с входными параметрами писать выходной блоб. Причем, целые числа могут быть как little endian, так и big endian.

И если там ошибка произойдет в коде, вся система станет раком, и придется вам в 4 часа утра включать ноут и удаленно перезагружать железку, получая от начальства нагоняй, что клиент N тысяч талеров впустую потерял из-за запоротых прошивок.

Вы:

  1. возьмёте опенсорсный sscanf, sprintf, ведь деды давно все эти проблемы решили; будете вручную трахаться с signed/unsigned и эндианнесс;

  2. возьмёте, и напишете свой кастомный sscanf, sprintf, с блекджеком и спецификаторами для эндианнес, и под конкретную задачу. Ведь вы же супер-кодер, один раз пару сложных процедур отладить - зато потом, как по автобану!

  3. sscanf, sprintf - для слабаков. Настоящий ковбой каждый раз пишет в буфер без вспомогательных процедур;

  4. позвоните маме, и скажете, что со следующей недели придется вам обедать у неё, а не на работе. Чтобы начинала варить борщи…

★★★★★

Последнее исправление: seiken (всего исправлений: 1)
Ответ на: комментарий от Bad_ptr

Не хочу, чтобы у АНБ был этот код.

seiken ★★★★★
() автор топика

В ТЗ блобы. При чем здесь scanf?

Если интерпретировать задачу более широко, то да, для кастомных форматов в эмбеддед только кастомная сериализация-десериализация. Особенно если это бинарный формат.

Если в прошивке нет scanf/sprintf, и они по какой-то причине действительно нужны (а не как в твоем примере), их относительно несложно реализовать на приемлемом уровне самостоятельно, либо портировать соответствующий кусок musl или uclibc.

Siborgium ★★★★★
()

Парсить блобы sscanf-ом можно, а зачем?

cobold ★★★★★
()

В данном случае sscanf просто как пример использования форматированного чтения. Там обработка блобов последовательная. Планируется всю память для них выделять статичечки. А в кастомном sscanf не будет собственно говоря строковой читаемой части, вся форматная строка будет состоять исключительно из спецификаторов.

seiken ★★★★★
() автор топика
Ответ на: комментарий от cobold

Ага. И питонячий модуль struct. Вкусняшка.

seiken ★★★★★
() автор топика

Уточню задачу, и обговорю, что может быть делать вообще надо.

Я работал с проприетарными микроконтроллерами, и у них есть спецификации и API. Если таковых нет, всегда можно связаться с людьми которые разбираются в этом. Если таких людей нет, ты вообще на какой-то странной работе работаешь.

Ты вообще не с той стороны к задаче подходишь. Какие к черту scanf, если сама задача - говно какое-о?

lovesan ★★☆
()
Ответ на: комментарий от lovesan

Данная тема чисто про кодирование на сишке. Всё, что нужно для решения задачи с т.з. взаимодействия с ОС уже имеется в наличии.

seiken ★★★★★
() автор топика
Ответ на: комментарий от seiken

Ну так если тебе задача так уж понятна (а мне почему-то кажется что нет), то отдай вон ее ИИ, пусть пишет.

lovesan ★★☆
()
Ответ на: комментарий от lovesan

Нет. Потому что когда отвалится, спрашивать будут с меня, а не с ИИ. ИИ - это как банк. Берешь бабло сейчас, а возвращать надо больше, чем взял.

seiken ★★★★★
() автор топика
  1. разобраться что там за формат такой, не мучать попу и использовать уже готовые решения. ASN.1 BER/DER? Protobuf? Fixed-width struct? bencode?

В крайнем случае писать свою FSM.

Парзить блобы scanf – это всё равно что парзить html regexp. Можно конечно, но только если у тебя пуле-непробиваемые ботинки.

beastie ★★★★★
()
Ответ на: комментарий от beastie

Формат выдумываю я сам, потому что это то, что разраб в моей роли выбирает. А грамматика там регулярная, так что парсинга там не нужно. А читалку/писалку TLV всё равно надо кодировать, и какой в ней смысл, если никакой интероперабельности нет и не будет? TLV полезен если твои блобы, вернее, их формат, где-то в виде официальной спеки висят, чтобы чужие дяди с твоими блоками умели работать, а иначе это оверкилл.

seiken ★★★★★
() автор топика
Последнее исправление: seiken (всего исправлений: 2)
Ответ на: комментарий от seiken

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

DI, мать их. А тестировать тогда можно в Линуксе на x86. О, как я придумал!

seiken ★★★★★
() автор топика
Ответ на: комментарий от seiken

Данная тема чисто про кодирование на сишке.

и про маму!

(особенно много про маму вошло в неизданное)

olelookoe ★★★★
()

6. Устрою себе празднWW игру в реверс.

sparkie ★★★★★
()

Представьте, что вам надо запрограммировать девайс на языке С.

вам надо

Для меня решение будет зависеть от того, что стоит за этими словами. Очень много вариантов, что значит «мне надо». Если надо по работе, буду привлекать доступные служебные ресурсы. Если это домашний проект, то зависит от приоритетов.

VIT ★★★
()
Ответ на: комментарий от seiken

Формат выдумываю я сам

Мюсьё заняться больше нечем? Такие чудачества только в хобби-проектах допустимы.

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

beastie ★★★★★
()

Вам надо в конечном счёте читать и разбирать блобы с входными параметрами писать выходной блоб. Причем, целые числа могут быть как little endian, так и big endian. И если там ошибка произойдет в коде, вся система станет раком, и придется вам в 4 часа утра включать ноут и удаленно перезагружать железку, получая от начальства нагоняй, что клиент N тысяч талеров впустую потерял из-за запоротых прошивок.

Широкий технический кругозор разработчика всегда побеждает узконаправленное мастерство, позволяя безошибочно принимать правильные технические решения. Чтобы решить твою задачу повышенной надежности, достаточно взглянуть туда, где сбой или отказ ПО приводит к потере человеческих жизней, а именно военно-промышленный комплекс, самолетостроение и современный автопром.

Вояки давно пришли к выводу, что для обеспечения безотказности работы ПО следует использовать кодогенератор. Обычно последовательность действий следующая:

  1. Моделируем работу своего ПО в «Матлабе/Симулинке».
  2. Создаем много тестов и прогоняем их.
  3. Сверяем результаты работы ПО с требованиями к нему.
  4. Запускаем кодогенератор под требуемый язык, процессор, операционку.
  5. Прогоняем тесты на этом сгенерированном коде и сверяем окончательный итог.

На «Ютубе» полно роликов об этом. Для ознакомления с технологией разработки сверхнадежного ПО этого будет достаточно. Дальше сам решишь каким способом решать задачу.

Enthusiast ★★★☆
()
Ответ на: комментарий от beastie

Это область анального огораживания системы и её контента. Здесь каждое второе решение - велосипед.

seiken ★★★★★
() автор топика
Ответ на: комментарий от Enthusiast

Вояки давно пришли к выводу

Правильно так: «Воякам в условиях мирного времени от нечего делать… захотелось красить траву и кантики на кроватях отбивать».
А вот в условиях военного времени «синус может достигать 4х».
Ну собсно вояки мирного времени уже проигрывают обычным гражданским коммерческим «тяп ляп и в продакшн» конторам

Bad_ptr ★★★★★
()
Ответ на: комментарий от Enthusiast

Запускаем кодогенератор под требуемый язык

Это ты сейчас ASN.1 описал. :)

beastie ★★★★★
()

Прям половина моей жизни.. Если ресурсы позволяют, то стандартные функции из string.h, если нет — то пишем сами.

На работе, кстати, ем домашнее — экономлю.

aiqu6Ait ★★★★★
()
Ответ на: комментарий от seiken

Интероперабельность бывает не только горизонтальная но и с самим собой во времени.

Вот тебе конкретный актуальный пример. Есть такая вещь как Two-line element set – используется для каталогизации спутников и мусора не орбите. Там под ID спутника отведены 5 знаков. Лет 60 его вполне хватало. Но вот незадача (и спасибо маску за мусор на орбите) – буквально пару недель назад запустили спутник под номером 100000. И теперь куча софта поломается.

Этокий y2k баг но по новому. ;) (Этим же и GPS (wikipedia.org) страдает)

beastie ★★★★★
()
Последнее исправление: beastie (всего исправлений: 2)
Ответ на: комментарий от beastie

спасибо маску за мусор на орбите

Ежели Трамп введёт пошлины на мусор Маска, то найдётся способ почистить орбиту и уложиться в 5 знаков.

quickquest ★★★★★
()
Ответ на: комментарий от beastie

Это какие-то геостратегические задачи в масштабе юрского периода. Я маленькая пешка. Говорят «копай тут» - копаю тут, говорят «стой» - стою.

seiken ★★★★★
() автор топика
Ответ на: комментарий от KivApple

да, это само собой разумеющееся. Т.к. этому учат в детском садике сишного образования, я даже не счёл это необходимым добавлять.

seiken ★★★★★
() автор топика

Я бы реализовал при помощи FSM с кольцевым буфером для возврата назад.

iron ★★★★★
()
Последнее исправление: iron (всего исправлений: 1)

Это случай когда ты помогаешь написать регвыр, просящий каждый раз вводит новые правила: типа а вот там может быть так, а числа могут быть такие, а теперь вот такие не захватывает и в какой-то момент это уже надоедает. Составить то регвыр не сложно, при знании всех входящих параметров.

AZJIO
()
Ответ на: комментарий от dataman

Ты бы ещё предложил возвращать в оборот номера паспортов после смерти их владельцев.

А возвращение в оборот сим-карт тебя не смущает?

quickquest ★★★★★
()
Ответ на: комментарий от beastie

что бы следующие 50 лет спать спокойно, а не поддеживать вечно ломающийся велосипед

К сожалению, в профессиональной среде бывает так, что спать спокойно == 50 лет кормиться с поддержкой велосипедов.

aiqu6Ait ★★★★★
()

sscanf, sprintf - для слабаков. Настоящий ковбой каждый раз пишет в буфер без вспомогательных процедур;

foror ★★★★★
()
Ответ на: комментарий от Enthusiast

Цимес тут в том что сишка для ковыряния байтиков/битиков такая же убогая нетехнологичная дрянь как и для всего остального, и «удобна» она только если она генерируется каким-то другим средством, без необходимости пропускать сишкины макароны через человеческий мозг. А ТС, вроде как, втихаря тоскует по аде. @seiken, а как бы она подошла для такого?

zurg ★★
()
Ответ на: комментарий от zurg

а как бы она подошла для такого?

Возможно, даже, что ещё хуже. Ада для байтодрочинга не особо подходит. va_list и ко. там не было и не будет, по определению. Слишком строгая система типов. С т.з. батареек и их наличия, даже операции с большими целыми (например, нужно для RSA) в опенсорсе вообще не видел на Аде вплоть до 2020+г. или около того, когда какие-то скубенты что-то выложили, а AdaCore подцепили. А на сишке этого добра вроде бы давно уже навалом.

Ну и авторы системного софта железяки, судя по всему, сишники 999 левела с бородой (а может ещё и лысые уже). Если у них попросить помощи с Адовым кодом, скорее всего, пошлют нафиг, как занятые профессора посылают студента-недотёпу.

seiken ★★★★★
() автор топика

Не помню, когда я последний раз пользовался sscanf. Возможно, вообще никогда. Может быть, когда изучал Си. Сомнительная функция, провоцирующая ошибки, лучше парсить строки другими способами.

firkax ★★★★★
()
Ответ на: комментарий от Lordwind

Там вопрос не в оплате, как я понимаю, а в ограниченном спектре возможностей.

aiqu6Ait ★★★★★
()

sscanf, sprintf - для слабаков. Настоящий ковбой каждый раз пишет в буфер без вспомогательных процедур;

Для итогового решения, вариант 3.

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

Для тестов и прототипов (Proof of Concept) сгодится любая дичь. Потому что вариант предложенного решения может и не взлететь.

sscanf() и sprintf() в девайсах - это вообще мовитон, допустим лишь snprintf().

Автор, а в чем, собственно, у тебя вопрос, это же вроде бы очевидные вещи, причем не зависящие от языка программирования, не?

Vic
()
Последнее исправление: Vic (всего исправлений: 1)
Ответ на: комментарий от seiken

«Читальщик» пишут не абы как хочется, а проектируют исходя из условий, как будут получены порции данных. Т.е. формат выбирается так, чтобы при любых условиях получить порцию данных, не противоречащих формату в любых ситуациях: мин/макс размер порции, разрыв, дубли, склеивание (буферизация), искажение и т.д. и т.п.

Например, 802.3 (наш обычный Ethernet), требует достаточно качественной линии связи, BER (Bit Error Ratio) не менее 1E-10 (ну или около того).

Vic
()
Последнее исправление: Vic (всего исправлений: 1)

блобы с входными параметрами писать выходной блоб

а зачем тут sscanf/sprintf, если это блобы?
в качестве sprintf можно взять stb'шный. little/big endian к sprintf/scanf не относится. Но если эти тьребования вызывают трудности - возможно действительно стоит обратиться к 4 пункту на время поиска более высокоуровневой работы, если это лучше даётся

mittorn ★★★★★
()
Ответ на: комментарий от Vic

пардон, а почемы вы ответили таким комментом? Совершенно же нерелевантные вещи. Уровень от физического вплоть до прикладного (исключая прикладной) модели OSI меня в данной задаче совершенно не интересуют.

seiken ★★★★★
() автор топика
Ответ на: комментарий от seiken

пожалуй, за исключением одной детали - эндианнесс, это очень важно

seiken ★★★★★
() автор топика
Ответ на: комментарий от aiqu6Ait

В зависимости от того, что нужно парсить.

Например парсер ip:port у меня выглядит так:

extern int strp_to_ip4_addr_port(char const ** st, uint32 * ip, uint16 * port){
  char const * s;
  uint8 t[4];
  s  = *st;
  if(*s==':') {
    s++;
    if(strp_to_uint16(&s, port)<0) return -1;
    *st = s;
    return 2;
  }
  if(strp_to_uint8(&s,t)<0 || *(s++)!='.' ||
     strp_to_uint8(&s,t+1)<0 || *(s++)!='.' ||
     strp_to_uint8(&s,t+2)<0 || *(s++)!='.' ||
     strp_to_uint8(&s,t+3)<0) return -1;
  if(*s==':') {
    s++;
    if(strp_to_uint16(&s, port)<0) return -1;
    *ip = t[0]*0x1000000 + t[1]*0x10000 + t[2]*0x100 + t[3];
    *st = s;
    return 3;
  }
  *ip = t[0]*0x1000000 + t[1]*0x10000 + t[2]*0x100 + t[3];
  *st = s;
  return 1;
}
strp_to_XXX - тоже мои функции, т.к. в libc только strtoul похожее есть, но оно жрёт всякие нежелательные символы, чего делать без спросу нельзя, и просто имеет неудобное апи.

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

firkax ★★★★★
()
Ответ на: комментарий от beastie

Верно, так и должно быть. Задача была распарсить айпи-адрес в его нормальном виде и выдать ошибку на всём остальном. Когда функция внутри себя поддерживает кучу всего разного, которое ты сходу и не помнишь (и при случае забудешь учесть) - это в итоге приводит к багам. На примере того же strtoul: может распарсить -1 как ULONG_MAX (ты уверен, что это всегда то что хотел программист?), может признать валидной строку с некими символами в начале, список которых зависит локали (isspace), молча признаёт одинаковыми 123 и 0х123 если указана шестнадцатеричная система. А ведь иногда успешный парсинг считают за валидацию входных данных, и эта строка с не пойми чем в начале и вероятно знаковая уйдёт куда-то где это всё точно не поддерживается и приводит, например, к какой-нить уязвимости. Как итог, перед вызовом strtoul придётся обкладываться доп. проверками на валидность числа (что оно реально начинается с цифры, что после неё нет буквы x или X итд). И упомянутый scanf тоже слишком умный и умеет например при некоторых обстоятельствах пропускать входные символы, не подошедшие под шаблон. Что там в итоге может напарсится из рандомного мусора, остаётся только гадать, в то время как правильным будет упасть с ошибкой и прекратить работу с сомнительными данными.

firkax ★★★★★
()
Ответ на: комментарий от Bad_ptr

Ну собсно вояки мирного времени уже проигрывают обычным гражданским коммерческим «тяп ляп и в продакшн» конторам

Проигрывают в чем? Конторы «тяп ляп» могут по военным контрактам проотвечаться и присесть в полном составе.

slackwarrior ★★★★★
()
Закрыто добавление комментариев для недавно зарегистрированных пользователей (со score < 50)