我收到缓冲区溢出:来自hp fortify的格式字符串警告。
你能告诉我双倍价值的最大长度吗?
在以下示例中,dCode
是一个double值,存储在pszPref
。
代码:
TCHAR pszPref[64];
_stprintf(pszPref, "%f", dCode);
我只是想确认dCode可以有或没有十进制值的最大长度。
答案 0 :(得分:0)
由于基数10基数通常不是浮点的最自然表示,因此没有最大字符串长度:显示精确浮点数可能需要无限数量的基数10位。
幸运的是,对于IEEE754浮点双,15个有效数字就足够了。如果你写了然后读回一个具有这个精度的浮点双,那么你将获得与你开始时相同的数字。 (使用"%.15E"
作为printf
样式格式化程序。)虽然C ++标准不坚持double
是该类型,但最常见的是,并且在MFC作为目标的系统上,它可能是。
您可以通过选中std::numeric_limits<double>::is_iec559
来测试(几乎)确定。
答案 1 :(得分:0)
由于您没有为格式提供精确参数,printf
并且它的亲戚默认使用6位十进制数字。
iee 754双精度浮点的最小值为-1.7976931348623157E+308
要打印精确到6位十进制数的数字,您需要一个符号字符,一个用于小数点,308个数字用于整数部分,6个十进制数字用于总共316个字符。别忘了为null终止符分配额外的字符。因此,317个字符的数组应该足够,但仅当使用iee 754时,c ++标准不保证。
hp fortify可能并不知道并且无论如何都不能安全地假设iee 754,所以无论你使用多大的阵列,你都可能无法摆脱警告。要确保不发生溢出,请使用允许传递缓冲区大小的snprintf
或类似内容。
答案 2 :(得分:0)
虽然没有完全回答您的问题,但您可以使用std::to_string来使用char数组。
即:
std::string strPref = std::to_string(dCode);
注意:如果您遇到Visual Studio 2010,则必须将dCode强制转换为mentioned in this answer。
答案 3 :(得分:0)
sprintf
,strcpy
,strcat
等)时,无论目标缓冲区实际有多大,Fortify都会产生该警告。近年来,微软已经制作出了“安全”的产品。所有这些方法的版本都有_s
扩展名。例如_stprintf_s
。
这些方法改进了截断版本(snprintf
等),因为如果发生溢出,它们会调用error handler。截断方法不会溢出缓冲区,但理论上它们可用于制作一些无效的缓冲区内容,这些内容会导致可能被黑客用作攻击媒介的连锁错误。
因此,为了保护您的代码并关闭Fortify:
使用处理溢出错误的回调方法调用_set_invalid_parameter_handler
(stdlib.h
)。
使用_stprintf_s(pszPref, sizeof(pszPref)/sizeof(pszPref[0]), "%f", dCode)
。