Sto eseguendo un sistema di metallo nudo con un ARM Cortex-M3 (STM32F205). Quando provo ad usare snprintf()
con numeri float, per es .:snprintf() stampa garbage floats con newlib nano
float f;
f = 1.23;
snprintf(s, 20, "%5.2f", f);
ho rifiuti in s
. Il formato sembra essere onorato, cioè la spazzatura è una stringa ben formata con cifre, punto decimale e due cifre finali. Tuttavia, se ripeto lo snprintf
, la stringa potrebbe cambiare tra due chiamate.
virgola mobile matematica sembra funzionare in caso contrario, e snprintf
opere con numeri interi, ad es .:
snprintf(s, 20, "%10d", 1234567);
io uso l'attuazione newlib-nano
con l'interruttore -u _printf_float
linker. Il compilatore è arm-none-eabi-gcc
.
Ho un forte sospetto di problemi di allocazione della memoria, poiché gli interi sono stampati senza intoppi, ma i float si comportano come se fossero corrotti durante il processo. Le funzioni familiari printf
chiamano malloc
con float, non con numeri interi.
L'unico pezzo di codice non appartenente a newlib
che sto usando in questo contesto è il mio _sbrk()
, che è richiesto da 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;
}
Per quanto sono stato in grado di tracciare, questo dovrebbe funzionare. Sembra che nessuno lo chiami mai con incrementi negativi, ma suppongo che ciò sia dovuto al design del newlib malloc
. L'unica cosa leggermente strana è che la prima chiamata a _sbrk
ha un incremento pari a zero. (Ma questa potrebbe essere solo la curiosità di malloc
sull'indirizzo di partenza dell'heap.)
Lo stack non deve entrare in collisione con l'heap, in quanto vi sono circa 60 KiB RAM per i due. Lo script linker potrebbe essere folle, ma almeno gli indirizzi heap e stack sembrano essere corretti.
Si noti che quelli sono 'double's, non' float's. Non importa se è importante, non si può passare comunque un 'float' a' snprintf() '. – unwind
Il prototipo di ['snprintf()'] (http://pubs.opengroup.org/onlinepubs/9699919799/functions/snprintf.html) è 'int snprintf (char * limita s, size_t n, const char * riduci il formato , ...); 'Non stai chiamando la funzione in base al prototipo. Hai '#include' ** e compilato con tutti gli avvisi abilitati **? –
pmg
Sicuramente il tuo vero codice sta usando 'snprintf()' e non 'sprintf()'? – chux