vsnprintf返回给定缓冲区大小的大小

时间:2017-04-03 07:23:18

标签: c++ c linux api

带有myPrint()函数的非常长的字符串将崩溃。

我认为vsnprintf()无法从linux手册页返回缓冲区长度的书面大小。

我期望的字符串是缓冲区大小的截断字符串,但是从测试代码下面完全错误。

下面有什么问题?

public final char CH = ',';

2 个答案:

答案 0 :(得分:6)

不,vsnprintf非常具体地返回完整字符串所需的字符数。 C11 7.21.6.12p3

  

vsnprintf函数返回 写入的字符数已足够大,不计算终止空字符,如果编码则返回负值发生了错误。因此,当且仅当返回值为非负且小于n时,才会完全写入以null结尾的输出。

此外,输入大小应该是完整的缓冲区大小,例如这里是512.然后vsnprintf将写入最多511个字符,并在写完最后一个字符后添加终止'\0'(C11 snprintf description)

  

否则,丢弃n-1之外的输出字符而不是写入数组,并且在实际写入数组的字符末尾写入空字符。如果在重叠的对象之间进行复制,则行为未定义。

另外,请注意(7.21.6.5p2):

  

[...]因此,当且仅当返回值为非负且小于n时,才会完全写入以null结尾的输出。

也就是说,如果你的缓冲区是一个512 char的数组并且你传入了512,那么如果n的返回*snprintf值是{{}},则该字符串被正确写入并且不会被截断{1}}

请注意,Microsoft Visual C ++的名称_vsnprintf具有非常破碎的功能:

  

[...]如果要写入的字符数小于或等于count,则返回写入的字符数; 如果要写入的字符数大于count,则这些函数返回-1表示输出已被截断。

最后,如果您只编写Linux / Glibc特定代码,您还可以考虑使用0 <= n <= 511来动态分配足够大的缓冲区来保存整个字符串。

答案 1 :(得分:2)

这里有很多事情需要解决:

  1. 您可以将完整的缓冲区大小提供给vsnprintf

    int r = vsnprintf(buffer, sizeof buffer, fmt, arg);
    
  2. 调用后无需终止缓冲区。 vsnprintf正确截断太长的字符串。

  3. 如果没有发生截断,
  4. vsnprintf会返回原来的长度。如果需要检测截断,可以按如下方式执行:

    if(r >= sizeof buffer) {
         // Buffer was too small    
    }