文章目录
- 小结
- 问题及解决
- 参考
小结
使用sprintf(...)
进行格式化是一种标准的做法,但是这样做是有一个极大的风险,由于sprintf(...)
不进行边界检查,这样会有写操作溢出边界的风险,并导致程序崩溃。本文进行了简单写操作溢出边界的测试,模拟程序崩溃,并建议了更为安全的snprintf(...)
方法进行格式化。
问题及解决
众所周知,sprintf(...)
不进行边界检查,再加上double
或者是float
的内建的数据类型一起使用(有时候会是一个比较大的正数),比较容易出现写操作溢出边界并导致程序崩溃,已经是臭名昭著了。
以代码sprintf(str, "%.2fMB(%.2f%%)", double_a, double_b);
为例。
sprintf
的说明指示符%.2f
规定了小数点后面截取两位,但小数点前面有多少位就采用多少位,例如像2.4008127812204012E+159
这样的大数,基本上小数点前面就超过160位数字了。如果数组str
比较小,就抓瞎了,写操作会溢出边界,并致程序崩溃。这种错误有时候极难定位,浪费很多宝贵的时候来找bug。
如果采用比较安全的做法, 例如: snprintf(str_short, 30, "%.2fMB(%.2f%%)", double_a, double_b);
,规定了边界,只写入前29位(最后再加一个结尾符),这样就不用担心写操作会溢出边界的问题了。
以下是程序测试很好地模拟了几种情况(double_a
是一个很大的数,double_b
是一个很小的数):
输出结果:
参考
sprintf(str,“%f”, voltage_temp ); works in C but not C ++C++ Buffer Overflow: Format String (%f/%F)Stackoverflow: understanding the dangers of sprintf(…)C++ float and double