我正在运行一个带有ARM Cortex-M3 (STM32F205)的裸机嵌入式系统。当我尝试使用snprintf()
函数处理浮点数时,例如:
float f;
f = 1.23;
snprintf(s, 20, "%5.2f", f);
我得到了垃圾数据存入s
中。格式似乎是正确的,也就是说,垃圾数据是一个由数字、小数点和两位小数组成的格式良好的字符串。然而,如果我重复使用snprintf
函数,该字符串可能会在两次调用之间更改。
浮点数运算似乎工作正常,并且snprintf
函数适用于整数,例如:
snprintf(s, 20, "%10d", 1234567);
我使用带有-u _printf_float
链接器开关的newlib-nano
实现。编译器是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对堆起始地址的好奇心。)堆和栈不应该相互冲突,因为两者共有大约60 KiB的RAM。链接脚本可能有点疯狂,但至少堆和栈的地址似乎是正确的。
snprintf()
的原型是int snprintf(char *restrict s, size_t n, const char *restrict format, ...);
。你调用函数的方式与原型不符。请确认是否已经添加了头文件<stdio.h>
,并开启了所有的编译警告。 - pmgsnprintf()
而不是sprintf()
吗? - chux - Reinstate Monica%f
通常涉及将float
转换为double
;EABI 强制要求double
的 8 字节对齐;而你的_sbrk()
只在分配时强制执行 4 字节对齐。这对于printf()
和malloc()
的内部机制有多大影响可能取决于具体情况,但进行实验应该很简单。 - Notlikethat-u_printf_float
会占用多少额外的闪存空间吗?我正试图为一个16kB的芯片(STM32F030F4P6)进行编译,但是二进制文件似乎太大了(约20 kB)。 - Christoph