C IAR微控制器中的sprintf腐蚀阵列
我目前正在学习嵌入式编程,因此正在使用带有ARM架构的TI微控制器的IAR平台上工作。由于我对此类编程或一般的C编程的技术细节一无所知,我想问一个基本问题: 我有以下简单的代码片段:C IAR微控制器中的sprintf腐蚀阵列,c,embedded,microcontroller,printf,C,Embedded,Microcontroller,Printf,我目前正在学习嵌入式编程,因此正在使用带有ARM架构的TI微控制器的IAR平台上工作。由于我对此类编程或一般的C编程的技术细节一无所知,我想问一个基本问题: 我有以下简单的代码片段: int i; for(i = 0; i < NUM_SAMPLES; i++) { sinTable[i] = sinf(2*i*dT*PI); } for(i = 0; i < NUM_SAMPLES; i++) { char out[32]; sprintf(out,"s
int i;
for(i = 0; i < NUM_SAMPLES; i++)
{
sinTable[i] = sinf(2*i*dT*PI);
}
for(i = 0; i < NUM_SAMPLES; i++)
{
char out[32];
sprintf(out,"sin: %.7f, %.7f;", i*dT, sinTable[i]);
putString(out);
delay(DELAY_100US);
}
inti;
对于(i=0;i
其中,sinTable[]
是大小为NUM_SAMPLES
的全局变量,putString(*char)
是一个写入RS232端口的函数,delay(float)
是一个简单的延迟函数
我的问题是,一旦调用sprintf(…)
,它就会破坏sinTable
,在COM信号的接收端绘制表格时会产生一些非常奇怪的结果
我不希望内存耗尽,因为MC有64KB的SRAM
有人有什么想法吗?您似乎非常确信结果字符串只有31个字符长。使用sprintf语句损坏另一个变量的唯一方法是结果字符串长度超过32字节(31个字符和一个nul字节),因此会覆盖内存的其他部分。使数字变小或使临时缓冲区变大。当到达
main
时,确保堆栈指针位于64位边界上
您看到的症状是典型的堆栈在奇数32位边界上对齐。在将double用作variadac参数之前,一切似乎都正常工作。当代码期望此类参数在8字节边界上时,这种情况就会中断。感谢所有对此问题提出解决方案的人。我最终编写了一个转换方法,该方法给出了字符串的十六进制表示形式,并将其传输,完全省略了
sprintf(…)
它非常粗糙,但适合我的需要。进一步检查后:
我怀疑Michael Burr关于堆栈利用率的回应是正确的。选择一个较小的printf库可能就足够了,但如果您可以增加堆栈大小,这似乎更安全。请注意,《IAR C/C++开发指南》包含链接器堆栈使用分析的信息
原件:
当我从IAR 6.1(许可)升级到6.4(kickstart)时,我遇到了一个类似的问题——vsnprintf写入“整个RAM”,尽管返回值表明写入的字符数在目标范围内。“解决方案”是避免使用支持多字节的printf库
项目选项>常规>库选项>打印不带多字节的小文件
可能还想取消选中
项目选项>C/C++编译器/语言2/启用多字节
我试图向IAR报告此事,但由于我的支持合同到期
不幸的是,IAR 7.3.4又出现了类似的问题,多字节“修复”似乎还不够。sprintf()和snprintf()都会发生这种情况,尽管这两种情况下的越界损坏不完全相同。采样数有多高,
dT
的值是多少?sprintf
不会损坏sinTable,除非它已经损坏。我要研究两件事:1)IAR的运行时有关于printf()
函数系列支持级别的选项。我认为默认情况下通常不启用浮点支持—请确保已启用它;2) 函数的printf()
系列使用了相当多的堆栈空间。确保分配给任务的堆栈足够大。@汤姆:尝试将char out[32]
更改为char out[200]
。还可以尝试将字符输出[32]
更改为静态字符输出[32]
,并告诉我们这是否会改变任何内容。这不是一个真正的解决方案,但结果可能会给我们一些线索。除非有中断例程覆盖背景上的随机内存位置,否则它闻起来像某种溢出。您没有收到任何编译器警告?您可以尝试启用备注(编译器和链接器),以查看编译器是否看到任何可疑的内容。还可以启用链接器映射创建,并查看是否有任何靠近sinTable
的内容可能在那里溢出。使用调试器,我发现内存区域没有重叠。假设它仍然显示,并且没有显示在调试器中,当选择字长256时,结果仍然相同。