_snwprintf_s的潜规则

在程序中为了构造文件全路径时,使用了函数_snwprintf_s。结果在释放buffer时运行时库(runtime library)报错,提示buffer已被破坏了。再次审视代码,看不出有什么毛病,只得动手调试,然后便定位问题出在了_snwprintf_s的调用上。

_snwprintf_s函数的原型定义如下:

int _snwprintf_s( wchar_t *buffer, size_t sizeOfBuffer, size_t count, const wchar_t *format [, argument] ... );

在细致地阅读了MSDN中关于它的说明后才发现问题原因:

此函数第二个参数(size_t sizeOfBuffer)是以word (双字节)为单位的,而不是byte。问题找到,更改传入参数后,buffer corruption的问题消失。

但是,还有个奇怪的问题,也许你已注意到,如果第二个参数是以word为单位的,那第三个参数呢?不应该也是以word为单位吗?

可惜,不是。第三个参数依然还是以byte为单位,否则你的程序又不能工作了,只是这次错误将会更加地隐蔽。

你只能感叹:同样都是count,咋相差这么大呢!

这里再说说_XXX_printf_X等一系列相关的函数,如果你看了MSDN中关于snprintf的说明,你这定会惊讶于它众多的兄弟姐妹,个个相像,可绝对又各不相同:如_snprintf, _snwprintf, _snwprintf_s, _snwprintf_s_l:

  • sprintf是ANSI C所定义的函数之一,应该是最古老的一个,当然也是最容易受缓存区溢出攻击的一个
  • _snprintf: 多了一个“n”表示是多了一个描述buffer长度的参数,如果输入字串过长将被截断,毫不留情。
  • _snwprintf: 多了个“w”表示是字串为双字节字串,如unicode
  • _snwprintf_s:又多了个”s”后缀,表示是“Security Enhancement”。为了应对缓存区溢出攻击,而对函数进行改进以对输入参数进行多项检查。更多信息见于:MSDN
  • _snwprintf_s_l: 更进一步,又多了个“l”后辍,表示此函数支持字符集指定,而不是默认使用当前字符集。
  • _snwprintf_s_l_? : 不久的将来又将怎样演化呢 ?我且拭目以待。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注