青岛网站建设服务中心,网站备案需要年检吗,国家企业信息公示系统全国,产品互联网营销推广文章目录小结问题及解决参考小结
使用sprintf(...)进行格式化是一种标准的做法#xff0c;但是这样做是有一个极大的风险#xff0c;由于sprintf(...)不进行边界检查#xff0c;这样会有写操作溢出边界的风险#xff0c;并导致程序崩溃。本文进行了简单写操作溢出边界的测…
文章目录小结问题及解决参考小结
使用sprintf(...)进行格式化是一种标准的做法但是这样做是有一个极大的风险由于sprintf(...)不进行边界检查这样会有写操作溢出边界的风险并导致程序崩溃。本文进行了简单写操作溢出边界的测试模拟程序崩溃并建议了更为安全的snprintf(...)方法进行格式化。
问题及解决
众所周知sprintf(...)不进行边界检查再加上double或者是float的内建的数据类型一起使用有时候会是一个比较大的正数比较容易出现写操作溢出边界并导致程序崩溃已经是臭名昭著了。
以代码sprintf(str, %.2fMB(%.2f%%), double_a, double_b);为例。
sprintf的说明指示符%.2f规定了小数点后面截取两位但小数点前面有多少位就采用多少位例如像2.4008127812204012E159这样的大数基本上小数点前面就超过160位数字了。如果数组str比较小就抓瞎了写操作会溢出边界并致程序崩溃。这种错误有时候极难定位浪费很多宝贵的时候来找bug。
如果采用比较安全的做法, 例如 snprintf(str_short, 30, %.2fMB(%.2f%%), double_a, double_b);规定了边界只写入前29位(最后再加一个结尾符这样就不用担心写操作会溢出边界的问题了。
以下是程序测试很好地模拟了几种情况double_a是一个很大的数double_b是一个很小的数 char str[200];char str_short[30];double double_a 2.4008127812204012E159;double double_b 1.3906711615670009E-309;cout double_a double_a endl;cout double_b double_b endl;//以下代码不会出现溢出边界程序正常运行sprintf(str, %.2fMB(%.2f%%), double_a, double_b);cout str string strStorage endl;//以下代码会出现溢出边界并导致程序崩溃, 注释之//sprintf(str_short, %.2fMB(%.2f%%), double_a, double_b);//cout str_short string str_short endl;//以下代码是比较安全的做法进行有效的边界检查 不会出现溢出边界程序正常运行输出了29位数字后接一个结尾符snprintf(str_short, 30, %.2fMB(%.2f%%), double_a, double_b);cout str_short string str_short endl;system(pause);return 0;输出结果
double_a 2.40081e159
double_b 1.39067e-309
str string 2400812781220401246196118053255811918339999978374591715533604156445593861118215728144462510983065193819073699313679732935503602200085321608454731838025375940608.00MB(0.00%)
str_short string 24008127812204012461961180532
Press any key to continue . . .
参考
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