Няшная / Говнокод #28320 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
// Heap memory allocate function (must not be used!)
caddr_t _sbrk(int incr) {
    <...>
    void some_bastard_called_sbrk();
    some_bastard_called_sbrk(); // Produce linker error in case it is used
}

_ATTRIBUTE ((__format__ (__printf__, 1, 2)))
int	printf (const char *__restrict format, ...)
{
    <маленький трехколесный велосипед>
}

int	putchar(int c) 
{
    <...> 
}
int	puts(const char *s) 
{
    <...> 
}

_ATTRIBUTE ((__format__ (__printf__, 2, 3)))
int	sprintf (char *__restrict s, const char *__restrict format, ...)
{
    <...> 
}

STM32. Я просто хочу использовать printf для вывода в последовательный порт и не течь. Ведь для этого нужно только реализовать int _write(int file, char *data, int len) и всё. Ой, а почему иногда программа падает где-то в кишках рантайма?

Может, стек переполняется? Да нет, проверил, значения в норме...

Просто стандартная библиотека от ST - это не курсовая ардуинщика, тут все системно, хендлы потоков, дескрипторы устройств и управляющие структуры. При первом обращении printf (и sprintf тоже!) выделяет себе в куче около 400 байт. Замечательное решение, помогающее сэкономить память, если мы не используем стандартный вывод! А куча тут - это просто последовательно заполняемая область памяти, размеры которой задаются в linker script (я вообще 0 указал, я ведь не использую malloc). Проверять выход за пределы кучи мы, конечно, не будем - зачем, когда рядом такая замечательная, никому не нужная область стека.
Да, и если забыть отключить буферизацию setvbuf(stdin/stdout/stderr, NULL, _IONBF, 0); , то он выделит не 400 байт, а килобайт (на контроллере с 8K RAM).

В общем, ах, оставьте меня, сам все напишу.
Только надо еще putchar и puts реализовать, а то компилятор любит printf'ы оптимизировать. И не забыть, что puts добавляет перевод строки. Уф, вроде все.

Запостил: Steve_Brown Steve_Brown, (Updated )

Комментарии (22) RSS

  • > Да, и если забыть отключить буферизацию setvbuf(stdin/stdout/stderr, NULL, _IONBF, 0); , то он выделит не 400 байт, а килобайт (на контроллере с 8K RAM).

    Можешь использовать dprintf, ему никакой "FILE *" с "stdout" не нужен, только "int" с "STDOUT_FILENO"
    int dprintf(int fd, const char *format, ...)
    Ответить
    • Да там даже sprintf что-то себе выделяет, думаю, один хрен бы было.

      EDIT: Ну да: undefined reference to `some_bastard_called_sbrk'
      Ответить
  • тесновато у вас там)

    sbrk вроде и правда не нужен, нужно ммапить в кучу

    А вместо машинерии printf можно срать сисколом прямо в stdout (итебе еще повезло что там С++ с cout нет)



    зы: циферки вон уже принес расщирение позиксовое, которое реализует сёмантику printf, но без CRT а поверх прямо голово write
    Ответить
      • у меня в неконтролеррах все это есть


        без мму бркают наверное. Ну типа вот у нас есть память, вот отсюда до сюда стек, потом брк, потом хип. Брк туда сюда двигают, и текут

        так?
        Ответить
        • Зачем там вообще бырк. Выделяешь в линкер-скрипте (или даже сишке) статичный регион под кучу и течёшь.
          Ответить
          • Это надо зараннеее знать!

            а так можно динамически в рантайме выбирать, что под стек что под кучу
            Ответить
            • > динамически в рантайме выбирать

              Какая надёжность )))

              З.Ы. Это тебе не интел, там у стека ограничителей обычно нету. Разве что через MPU навертеть, но он не везде есть.
              Ответить
              • Ну, какая уж тебе надежность, если статус твоего тела (жив/не жив) является всего-навсего байтом в огромной таблице. И который в любой момент может стать False...
                Ответить
    • Ну дык - знал бы эбаут, срал бы в stdout... Точнее, сразу велосипед бы соорудил. Мне не столько памяти жалко, сколько от подляны такой обидно: завалиться ко мне в стек без проса и орать, что я что-то испортил.

      А сисколлы ты тут сам реализуешь. Рантайм же не знает, в какой порт ты срешь (а, может, вообще по SPI передаешь), так что пишешь какой-нибудь MySerialOutputChar(char c) { while (!TRANSMIT_BUF_EMPTY()); TRANSMIT(c); } , ну а если printf хочешь использовать, то подсовываешь ему _write(<...>) { while (len--) MySerialOutputChar(*data++); } и все типа работает.
      Ну, можно, конечно, везде MySerialOutputString понавтыкать, но хотелось же %d%08X.
      Ответить
  • Опытная сишкоблядь с легкостью решает не существующие в паскалье проблемы.
    Ответить
  • А вообще какие ЯП и какие библиотеки сейчас можно использовать с 8К RAM?
    Ответить
    • Не забывай, что на контроллерах всё-таки флешка есть, которая прилично больше оперативки. Т.е. код и константы в память пихать не обязательно.
      Ответить
      • Эх, микропитон на 8 не взлетит, к сожалению. В минималках 16 указано.
        Ответить
        • У тебя старый конпелятор, на котором они не константы?
          Ответить
        • сраковые литералы в неписуемой части озу, не ломай пальчики.
          Ответить
    • На джавасрипте.

      Пишеш закащику: «насяника у мене тут не влезает, нужно конь троллер по лучше»
      Ответить
    • Pawn, например. Статическая типизация, статическое распределение памяти и возможность исполнения из ROM.
      Ответить
  • Заблудился сталкер в лесу; идёт и кричит: "Эй, ау, кто-нибудь! Помогите!"
    Вдруг навстречу ему - здоровенная такая, страхолюдина, и говорит жалостливо:
    "Чего орешь, ужин ты мой?.."
    Ответить

Добавить комментарий

Я, guest, находясь в здравом уме и твердой памяти, торжественно заявляю:

    А не использовать ли нам bbcode?


    8