Здравствуйте, vdimas, Вы писали:
V>Если пользуешь Си, то для оперирования объявленными статическими данными (структурами, массивами) необходим CRT.
Что именно из CRT нужно для этого?
V>Просто напоминаю, что почти всегда микроконтроллеры выполнены по гарвардской ахитектуре, а не по фон-неймановской, с которой ты писал этот пост.
Весьма спорное утверждение. Из гарвардских видел только клоны MCS-51, хотя, не скажу, что большой опыт с различными семействами
V>Поэтому, такая инициализация в гарвардской бессмысленна, требует работы CRT в сочетании со специально-сгенерированным кодом на каждую такую инициализацию.
V>Например, в фон-неймановской архитектуре, проинициализированная глобальная переменная не требует лишнего кода, потому что в бинарном образе уже хранятся данные ровно так, как описаны в сниппете выше, т.е. загрузку этих данных выполняет внешний загрузчик. Но в микроконтроллере инициализацию переменной s должен выполнять код, прошитый в микрик — и ситуация резко меняется, не так ли?
Ничего не понял. Причем тут фон-неймановская архитектура? В любом случае, в ОЗУ инициализированные переменные должны как-то попасть, от архитектуры тут ничего не зависит.
Да, вспомнил, про STM32. Там у них уже есть кое-какой прошитый код, который собственно, и занимается всей инициализацией для запуска прошивки. Ещё этот встроенный бутлоадер анализирует пины BOOT0/BOOT1, и в зависимости от их состояния может переходить в режим общения по UART, через который можно обращаться к памяти читать/писать, или даже залить прошивку, без какого-либо ST-LINK'а
Здравствуйте, vsb, Вы писали:
vsb>Вроде общепринятая точка зрения, что C ближе всего к железу, ну если не считать языков ассемблера.
vsb>Очень забавно за всем этим наблюдать, конечно.
Да, кстати, не очень понятно, а причем тут язык C? Я думаю, ты можешь написать свою прошивку целиком на асме, и будет происходить всё то же самое
Здравствуйте, 777777w, Вы писали:
O>>... обнуляется ядром — потому что в ином случае это была бы утечка данных из какого нить соседнего процесса.
7>Офигеть шпиономания. А как наш процесс мог этим воспользоваться?
Про спектр и мельдоний уязвимости слышал? А там шпиономания уже на порядок выше
Здравствуйте, vsb, Вы писали:
vsb>А при чём тут POSIX и C? Это как бы разные вещи. Не, я согласен, у меня printf тоже не линкуется, ему там ещё с десяток вызовов нужно реализовать
Странно, а у меня printf нормально линковался, и даже в кейловское окошко Output умел срать
Здравствуйте, vsb, Вы писали:
vsb>Я такого не знаю. Вообще было бы неплохо иметь язык, который уровнем чуть выше ассемблера. Ну чтобы там были if/for/while и тд, чтобы без goto простейшие вещи писать. Чтобы какая-то минимальная типизация была (ну к примеру signed/unsigned и компилятор знал, какие инструкции для сравнения генерировать). Чтобы функции писать и вызывать по-человечески, а не запоминать, сколько там аргументов и какого типа идут в регистры. Но в то же время чтобы вопросы "а не оптимизирует ли компилятор вечный цикл", "а можно ли передавать невалидный указатель в memcpy", "а можно ли разыменовывать 0?" даже смысл не имели. Чтобы каждая конструкция понятно и предсказуемо компилировалась в одну или несколько машинных инструкций.
Здравствуйте, Marty, Вы писали:
M>не вижу никакой memcpy, только memcmp. И про какие ещё две речь?
В самом верху же — __rt_memcpy и __rt_memcpy_w.
ЕМ>>Я в первую очередь про отладочные версии со встроенными проверками.
M>Проверками чего?
Параметров функций на вхоже, промежуточных адресов в процессе работы, результатов, возвращаемых из callback'ов, и прочего.
M>Мой вопрос был скорее по первому предложению.
Я недостаточно знаком с номенклатурой МК, чтобы утверждать уверенно, но, если в рамках одной серии есть модели с более и менее эффективным командами чтения/записи, то вполне логично использовать более эффективные команды. Проще всего это сделать, если МК имеет команду/регистр, откуда можно узнать его модель. Если не имеет, то это логично сделать на этапе компиляции, определяя нужную версию функции, но в заголовке, который может включаться в разные модули, это сделать не всегда просто.
M>Ассерты у нас обычно и так везде были пораспиханы (не в CRT, в своём коде)
Если функции CRT используются более-менее регулярно, неплохо иметь их и там.
M>про какие сообщения об ошибках в контексте МК ты пишешь — не очень понятно.
Если есть свободный UART, и памяти хватает — туда можно слать текстовые сообщения, хотя бы короткие. Есть экран — на него. Если подключен отладчик, можно его дергать. Если есть светодиод, им можно мигать.
M>ничего в голову не приходит, что бы могло понадобиться из CRT на микроконтроллере
Если МК обслуживает устройство с текстовым экраном, файловую систему, работает с модемом, GPS-приемником — строковые функции, вплоть до sprintf.
Здравствуйте, Marty, Вы писали:
M>Про спектр и мельдоний уязвимости слышал?
Я слышал, но ни одного работающего примера за несколько лет так и не увидел. На гитхабе валяется какой-то пример, но он сильно завязан под линукс, а я хотел проверить под виндой.
Здравствуйте, Marty, Вы писали:
M>у меня printf нормально линковался
С любым *printf сразу же возникает вопрос с поддержкой плавучки. Если программа ее не использует, то поддержка будет болтаться в коде мертвым грузом. В грамотной реализации должен быть параметр, управляющий созданием нужных ссылок на этапе компиляции.
Здравствуйте, Евгений Музыченко, Вы писали:
M>>не вижу никакой memcpy, только memcmp. И про какие ещё две речь?
ЕМ>В самом верху же — __rt_memcpy и __rt_memcpy_w.
А, да, проглядел.
M>>Мой вопрос был скорее по первому предложению.
ЕМ>Я недостаточно знаком с номенклатурой МК, чтобы утверждать уверенно, но, если в рамках одной серии есть модели с более и менее эффективным командами чтения/записи, то вполне логично использовать более эффективные команды. Проще всего это сделать, если МК имеет команду/регистр, откуда можно узнать его модель.
Если про STM32, то такого регистра нет. И они все армовские, там всё одинаково в плане команд, только периферия разная. Продетектить конкретную модель (или хотя бы линейку F1/F2/F3/F4) — можно, но геморно. И в рантайме для выбора реализации не имеет смысла.
ЕМ>Если не имеет, то это логично сделать на этапе компиляции, определяя нужную версию функции, но в заголовке, который может включаться в разные модули, это сделать не всегда просто.
Как и везде, define'ами. Я, собственно, так и делал. Задаёшь в проекте макрос STM32F105RB4, и всё только для этого проца актуальное используется
M>>Ассерты у нас обычно и так везде были пораспиханы (не в CRT, в своём коде)
ЕМ>Если функции CRT используются более-менее регулярно, неплохо иметь их и там.
Так вот я и пытаюсь понять, а какие функции CRT нужны. Кстати, тот пример, который я приводил, он от проекта, который писали до меня в основном, там много было чистой сишечки, в моих плюсовых проектах наверное и mem* не подсасывается
M>>про какие сообщения об ошибках в контексте МК ты пишешь — не очень понятно.
ЕМ>Если есть свободный UART, и памяти хватает — туда можно слать текстовые сообщения, хотя бы короткие. Есть экран — на него. Если подключен отладчик, можно его дергать. Если есть светодиод, им можно мигать.
А, ну это да. Я с нашими электронщиками ппц сколько бился, пока наконец не приучил их разводить отладочный UART
И светодиоды обычно были, и это использовалось
M>>ничего в голову не приходит, что бы могло понадобиться из CRT на микроконтроллере
ЕМ>Если МК обслуживает устройство с текстовым экраном, файловую систему, работает с модемом, GPS-приемником — строковые функции, вплоть до sprintf.
Ну, это да. Ну и всё, наверное. Хотя про printf уже вопросы. Я всегда без него обходился, он жирноватый больно. Я себе написал поток типа плюсового, получилось и компактнее, и быстрее в рантайме
Здравствуйте, Евгений Музыченко, Вы писали:
M>>у меня printf нормально линковался
ЕМ>С любым *printf сразу же возникает вопрос с поддержкой плавучки. Если программа ее не использует, то поддержка будет болтаться в коде мертвым грузом. В грамотной реализации должен быть параметр, управляющий созданием нужных ссылок на этапе компиляции.
Ты всё равно не выкинешь плавучку никуда. Вот у меня вывод через поток был сделан, и если плавучка не выводится, то соотв. operator<< не вызывается, и плавучку никто не тянет. С printf так не получится, там всё сразу вкорячено. Ну, только если пересобирать версию printf с отключенной поддержкой спецификаторов %f и тп
Здравствуйте, Marty, Вы писали:
M>Как и везде, define'ами. Я, собственно, так и делал. Задаёшь в проекте макрос STM32F105RB4, и всё только для этого проца актуальное используется
Как там решается проблема множественных определений одного и того же? Линкер сам выкидывает дублирующиеся определения?
M>Так вот я и пытаюсь понять, а какие функции CRT нужны.
Я ж привел в пример те же строковые. А где-то и сортировка нужна.
M>в моих плюсовых проектах наверное и mem* не подсасывается
Блоки памяти размером больше десятка байт не копируются, строки не используются? Или все реализовано вручную?
M>Я с нашими электронщиками ппц сколько бился, пока наконец не приучил их разводить отладочный UART
Ну так удобно же — натыкать везде, включая библиотеки и CRT, разных проверок, и выводить хотя бы имя файла и номер строки.
M>про printf уже вопросы. Я всегда без него обходился, он жирноватый больно.
Дык, именно потому, что хочет поддерживать все форматы, а это как раз требуется редко. Сделали б его давным-давно настраиваемым по какой-нибудь типовой модели — цены б ему не было.
M>Я себе написал поток типа плюсового, получилось и компактнее, и быстрее в рантайме
А я написал свой sprintf — тож и компактнее, и быстрее. Потоки выглядят слишком громоздко и невнятно, по виду выражения хрен поймешь, как будет выглядеть то, что выводится.
Здравствуйте, Marty, Вы писали:
M>С printf так не получится, там всё сразу вкорячено.
Дык, элементарно же: из *printf вызывать функции преобразования с известными именами, которые определяются в libc. Если программа явно определяет такие функции сама, то вызываются они, а стандартные из libc не тянутся. Но такое, наверное, делается только в особо грамотных реализациях, которые с заботой о программисте.
Здравствуйте, Евгений Музыченко, Вы писали:
M>>Как и везде, define'ами. Я, собственно, так и делал. Задаёшь в проекте макрос STM32F105RB4, и всё только для этого проца актуальное используется
ЕМ>Как там решается проблема множественных определений одного и того же? Линкер сам выкидывает дублирующиеся определения?
Если ты поподробнее раскроешь суть проблемы, то я расскажу, как она решается. Но пока не могу вспомнить, была ли подобная проблема
M>>Так вот я и пытаюсь понять, а какие функции CRT нужны.
ЕМ>Я ж привел в пример те же строковые. А где-то и сортировка нужна.
M>>в моих плюсовых проектах наверное и mem* не подсасывается
ЕМ>Блоки памяти размером больше десятка байт не копируются, строки не используются? Или все реализовано вручную?
Ну, строковые — да. Хотя, strlen возможно в рукопашную сделал, а копирование строк — а зачем? Для форматирования у меня свой класс потока, его можно было приаттачить как к UART, так и к буферу в памяти. Аттач к конкретной реализации производился через интерфейс ICharWritter, там посимвольно куда надо выводится.
Сортировка — std::sort
M>>Я с нашими электронщиками ппц сколько бился, пока наконец не приучил их разводить отладочный UART
ЕМ>Ну так удобно же — натыкать везде, включая библиотеки и CRT, разных проверок, и выводить хотя бы имя файла и номер строки.
Удобно, но имя файла выводить — не вариант, прошивка пухнет от этого. Просто кидается аппаратное исключение, и в отладчике смотришь, откуда туда попал
M>>про printf уже вопросы. Я всегда без него обходился, он жирноватый больно.
ЕМ>Дык, именно потому, что хочет поддерживать все форматы, а это как раз требуется редко. Сделали б его давным-давно настраиваемым по какой-нибудь типовой модели — цены б ему не было.
M>>Я себе написал поток типа плюсового, получилось и компактнее, и быстрее в рантайме
ЕМ>А я написал свой sprintf — тож и компактнее, и быстрее. Потоки выглядят слишком громоздко и невнятно, по виду выражения хрен поймешь, как будет выглядеть то, что выводится.
Поток я делал "а ля" — по мотивам плюсовых, но никакой совместимости со стандартными не предусмотрено. По виду выражения и не надо понимать в 99% случаем, как выводимое будет выглядеть. Как выведет, так и ладно. Это ж логи. Зато там нельзя обосраться с несоответствием форматной строки конкретным аргументам.
Здравствуйте, Евгений Музыченко, Вы писали:
M>>Про спектр и мельдоний уязвимости слышал?
ЕМ>Я слышал, но ни одного работающего примера за несколько лет так и не увидел. На гитхабе валяется какой-то пример, но он сильно завязан под линукс, а я хотел проверить под виндой.
Ну, это очень специфическая дырка в безопасности. А вот если бы память после других процессов не затирали бы, то эксплойты плодились бы как грибы после дождя
Здравствуйте, Marty, Вы писали:
M>Если ты поподробнее раскроешь суть проблемы, то я расскажу, как она решается. Но пока не могу вспомнить, была ли подобная проблема
Если в стандартных заголовках по определенному перед ними типу МК определяются только макросы, то проблемы нет. Она возникает, если нужно определять функции или глобальные переменные. В C++ из-за шаблонов добавили специальный параметр для линкера, чтобы не ругался на множественные определения, а выбирал одно. В типовом C такого нет, нужны извращения вроде специального отдельного заголовка, включаемого только в один модуль программы.
M>Сортировка — std::sort
Она, типа, в МК аппаратно реализована?
M>имя файла выводить — не вариант, прошивка пухнет от этого.
Компилятор не умеет собирать одинаковые строки в одну?
M>По виду выражения и не надо понимать в 99% случаем, как выводимое будет выглядеть.
А если нужно выводить текст на экран?
M>Зато там нельзя обосраться с несоответствием форматной строки конкретным аргументам.
Я всю жизнь использую *printf, такое случается гораздо реже других логических ошибок. Это еще один фетиш C++.
Здравствуйте, Marty, Вы писали:
M>>>Про спектр и мельдоний уязвимости слышал?
ЕМ>>Я слышал, но ни одного работающего примера за несколько лет так и не увидел.
M>Ну, это очень специфическая дырка в безопасности.
Почему специфическая? Она претендует на применимость на множестве популярных процессоров, после нее разработчикии ОС в срочном порядке выпускали патчи, а MS сподобилась изменить и кодогенератор в VC++. За столько лет уж кто-то должен был родить под винду хоть работающий пример, хоть троян, который его использует. Однако — тишина.
Здравствуйте, Евгений Музыченко, Вы писали:
M>>Если ты поподробнее раскроешь суть проблемы, то я расскажу, как она решается. Но пока не могу вспомнить, была ли подобная проблема
ЕМ>Если в стандартных заголовках по определенному перед ними типу МК определяются только макросы, то проблемы нет. Она возникает, если нужно определять функции или глобальные переменные. В C++ из-за шаблонов добавили специальный параметр для линкера, чтобы не ругался на множественные определения, а выбирал одно. В типовом C такого нет, нужны извращения вроде специального отдельного заголовка, включаемого только в один модуль программы.
Линкер и для C и для C++ один и тот же, если что. И всё равно ничего не понял, что за проблема, о каких извращения ты говоришь
M>>Сортировка — std::sort
ЕМ>Она, типа, в МК аппаратно реализована?
Она не нуждается в CRT, и помещается по месту
M>>имя файла выводить — не вариант, прошивка пухнет от этого.
ЕМ>Компилятор не умеет собирать одинаковые строки в одну?
Умеет, но даже десяток имён файлов легко съедят килобайт, что иногда довольно критично. А файлов у меня далеко не десяток
M>>По виду выражения и не надо понимать в 99% случаем, как выводимое будет выглядеть.
ЕМ>А если нужно выводить текст на экран?
Чрезвычайно редкий кейс, и там можно минутку потупить, ничего страшного
M>>Зато там нельзя обосраться с несоответствием форматной строки конкретным аргументам.
ЕМ>Я всю жизнь использую *printf, такое случается гораздо реже других логических ошибок. Это еще один фетиш C++.
Ну, твоё дело. А я каждый раз лезу в доки по printf, потому что все нюансы форматной строки не держу в голове. И это не фетиш, а удобство. И обсёры с форматной строкой встречаются регулярно, благо что современные компиляторы умеют о таких проблемах предупреждать
Здравствуйте, Евгений Музыченко, Вы писали:
M>>Ну, это очень специфическая дырка в безопасности.
ЕМ>Почему специфическая? Она претендует на применимость на множестве популярных процессоров, после нее разработчикии ОС в срочном порядке выпускали патчи, а MS сподобилась изменить и кодогенератор в VC++. За столько лет уж кто-то должен был родить под винду хоть работающий пример, хоть троян, который его использует. Однако — тишина.
Ну, соломку все подстелили, да. Но имхо эту дырку не просто использовать в практических целях. В отличие от неочищеной памяти
Здравствуйте, Marty, Вы писали:
M>Линкер и для C и для C++ один и тот же, если что.
Я в курсе. Но типовой линкер для C не в состоянии адекватно линковать все программы на C++. Обратное возможно.
M>ничего не понял, что за проблема, о каких извращения ты говоришь
Ну вот нужно в зависимости от типа МК определить не макрос, а функцию. Если ее просто определить в одном из стандартных заголовков, то она будет определена в каждом модуле, включающем этот заголовок, и обычный линкер этого не переварит. Поэтому нужен либо линкер с оптимизацией множественных определений, либо готовый набор нужных функций в libc на все случаи жизни, для которых в заголовке под видом общего имени функции будет определяться макрос.
M>>>Сортировка — std::sort M>Она не нуждается в CRT, и помещается по месту
Она и есть та часть CRT, которая реализована в заголовках в виде исходников, а не в libc в виде объектного кода.
M>Умеет, но даже десяток имён файлов легко съедят килобайт
Имен — не съедят, а вот путей — да. Именно поэтому было бы полезно или управлять раскрытием __FILE__, или иметь отдельный макрос только для имени.
ЕМ>>А если нужно выводить текст на экран?
M>Чрезвычайно редкий кейс
Производители миллионов гаджетов на МК с экранами смотрят на Вас с недоумением.
M>я каждый раз лезу в доки по printf, потому что все нюансы форматной строки не держу в голове.
Чего там держать-то для типовых форматов (d, u, x, s)? Это для плавучки там куча нюансов, а для целых и строк — раз-два и обчелся.
M>это не фетиш, а удобство
Я сильно сомневаюсь, что, если бы во всех руководствах по C++ не утверждалось, что только потоки — истинно правильный способ, а *printf — древнее и опасное убожество, большинство пользовалось бы потоками.
M>обсёры с форматной строкой встречаются регулярно
Гораздо реже, чем логические ошибки, приводящие к тем же последствиям — просто потому, что *sprintf в типовой программе гораздо меньше, чем других конструкций, чреватых неконтролируемыми ошибками.
M>современные компиляторы умеют о таких проблемах предупреждать
По уму, надо было изначально сделать эти предупреждения, а не пихать потоки везде, куда можно технически.