Я запускаю голую металлическую встроенную систему с ARM Cortex-M3 (STM32F205). Когда я пытаюсь использовать snprintf()
с номерами с плавающей точкой, например .:snprintf() отпечатки мусорных поплавков с newlib nano
float f;
f = 1.23;
snprintf(s, 20, "%5.2f", f);
Я получаю мусор в s
. Формат, по-видимому, заслуживает внимания, т. Е. Мусор представляет собой хорошо сформированную строку с цифрами, десятичной точкой и двумя конечными цифрами. Однако, если я повторяю snprintf
, строка может меняться между двумя вызовами.
с плавающей точкой математике, кажется, работает иначе, и snprintf
работы с целыми числами, например .:
snprintf(s, 20, "%10d", 1234567);
Я использую newlib-nano
реализации с помощью переключателя -u _printf_float
линкера. Компилятор: arm-none-eabi-gcc
.
У меня есть сильное подозрение в проблемах с распределением памяти, поскольку целые числа печатаются без каких-либо икота, но поплавки действуют так, как если бы они были повреждены в процессе. Семейные функции printf
вызывают malloc
с поплавками, а не целыми числами.
Единственный фрагмент кода, не относящийся к newlib
Я использую в этом контексте мой _sbrk()
, который требуется malloc
.
caddr_t _sbrk(int incr)
{
extern char _Heap_Begin; // Defined by the linker.
extern char _Heap_Limit; // Defined by the linker.
static char* current_heap_end;
char* current_block_address;
// first allocation
if (current_heap_end == 0)
current_heap_end = &_Heap_Begin;
current_block_address = current_heap_end;
// increment and align to 4-octet border
incr = (incr + 3) & (~3);
current_heap_end += incr;
// Overflow?
if (current_heap_end > &_Heap_Limit)
{
errno = ENOMEM;
current_heap_end = current_block_address;
return (caddr_t) - 1;
}
return (caddr_t)current_block_address;
}
Насколько я смог отслеживать, это должно сработать. Кажется, что никто никогда не называет его отрицательными приращениями, но я предполагаю, что это связано с дизайном newlib malloc
. Единственное немного странное, что первый вызов _sbrk
имеет нулевой приращение. (Но это может быть только malloc
's любопытство об исходном адресе кучи.)
Стек не должен сталкиваться с кучей, так как вокруг них около 60 KiB RAM. Сценарий компоновщика может быть безумным, но, по крайней мере, адреса кучи и стека кажутся правильными.
Обратите внимание, что это 'double', а не 'float'. Не знаю, если это имеет значение, вы не можете передавать 'float' в' snprintf() 'в любом случае. – unwind
Прототипом для '' snprintf() '] (http://pubs.opengroup.org/onlinepubs/9699919799/functions/snprintf.html) является' int snprintf (char * ограничивать s, size_t n, const char * ограничивать формат , ...); 'Вы не вызываете функцию в соответствии с прототипом. Вы '#include' ** и скомпилированы с включенными предупреждениями **? –
pmg
Уверен, что ваш истинный код использует 'snprintf()', а не 'sprintf()'? – chux