【问题标题】:Getting the length of a formatted string from wsprintf从 wsprintf 获取格式化字符串的长度
【发布时间】:2011-09-02 04:27:34
【问题描述】:

当使用标准 char* 字符串时,snprintfvsnprintf 函数将返回输出字符串的长度,即使该字符串由于溢出而被截断。* 似乎 ISO C 委员会没有就像他们添加 swprintfvswprintf 时的这个功能,它们在溢出时返回 -1。

有谁知道可以提供这个长度的函数吗?我不知道潜在字符串的大小。我可能要求太多,但是..我宁愿不:

  • 分配一个巨大的静态临时缓冲区
  • 反复分配和释放内存,直到找到适合的大小
  • 添加额外的库依赖
  • 编写我自己的格式字符串解析器

*我意识到 MSVC 不这样做,而是提供 scprintfvscprintf 函数,但我正在寻找其他编译器,主要是 GCC。

【问题讨论】:

  • 我从来不知道 MSVC 的 scprintf() 函数集。谢谢指点。

标签: c wchar-t


【解决方案1】:

我对您的最佳建议是根本不要使用wchar_t 字符串,特别是如果您不编写面向 Windows 的代码时。如果这不是一个选项,这里有一些其他的想法:

  1. 如果您的格式字符串本身不包含非 ASCII 字符,那么首先使用相同的参数集调用 vsnprintf 以获取以字节为单位的长度,然后将其用作长度的安全上限wchar_t 个字符(如果字符很少或非 ASCII 字符,则绑定会很紧)。

  2. 如果您同意引入对 POSIX 函数的依赖(可能会添加到 C1x),请使用 open_wmemstreamfwprintf

  3. 只是迭代分配更大的缓冲区,但要聪明:在每一步以几何方式增加大小,例如127, 255, 511, 1023, 2047, ...我比 2 的整数幂更喜欢这种模式,因为它很容易避免危险的情况,即 SIZE_MAX/2+1 的分配可能会成功,但在下一次迭代时会换成 0。

【讨论】:

  • 遗憾的是,我不是从头开始编写的——我正在修复/扩展现有的代码库。我不知道 open_wmemstream.. 这可能是个好方法。
  • 请注意,除非您处理的字符串大小分布非常分散,否则您可能会通过方法 3 获得最佳性能并选择至少与您处理的“大多数”字符串。我猜 127 就足够了。
【解决方案2】:

这将返回宽字符串的缓冲区大小:

vswprintf(nullptr, -1, aFormat, argPtr);

【讨论】:

  • 首先,在C语言中没有预定义的nullptr;这是 C++11 的一个属性。其次,该标准需要vswprintf() 的非空指针才能正常工作。第三,-1 参数将被解释为size_t,因此是巨大的。虽然这意味着您不会用完空间(因此您不会收到来自vswprintf() 的否定响应),但您仍然会遇到通过空指针写入的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-26
  • 1970-01-01
相关资源
最近更新 更多