带有myPrint()函数的非常长的字符串将崩溃。
我认为vsnprintf()无法从linux手册页返回缓冲区长度的书面大小。
我期望的字符串是缓冲区大小的截断字符串,但是从测试代码下面完全错误。
下面有什么问题?
public final char CH = ',';
答案 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)
这里有很多事情需要解决:
您可以将完整的缓冲区大小提供给vsnprintf
:
int r = vsnprintf(buffer, sizeof buffer, fmt, arg);
调用后无需终止缓冲区。 vsnprintf
正确截断太长的字符串。
vsnprintf
会返回原来的长度。如果需要检测截断,可以按如下方式执行:
if(r >= sizeof buffer) {
// Buffer was too small
}