带有myPrint()函数的非常长的字符串将崩溃.
我认为vsnprintf()无法从linux手册页返回缓冲区长度的书面大小.
我期望的字符串是缓冲区大小的截断字符串,但从测试代码下面完全错误.
下面有什么问题?
void myPrint(const char* fmt, ...)
{
char buffer[512] = {0,};
va_list arg;
va_start(arg, fmt);
int r = vsnprintf(buffer, 511, fmt, arg); // buffer size is given
if (r > 0) // works correctly
buffer[r+1] = '\0'; // crash because r is 200,000
va_end(arg);
}
int main(int, char**)
{
const char * data = "abcdefg...." // assuming that a length is 200,000 byte string
myPrint("%s\n", data);
}
Run Code Online (Sandbox Code Playgroud)
不,vsnprintf
非常具体地返回完整字符串所需的字符数.C11 7.21.6.12p3:
vsnprintf函数返回已经写入的字符数已足够大,不计算终止空字符,如果发生编码错误则返回负值.因此,当且仅当返回值是非负且小于n时,才完全写入以null结尾的输出.
另外,输入大小应该是完整的缓冲区大小,例如512.然后vsnprintf
将写入最多511个字符并'\0'
在写入最后一个字符后添加终止.(C11 snprintf说明):
否则,丢弃n-1之外的输出字符而不是写入数组,并在实际写入数组的字符末尾写入空字符.如果在重叠的对象之间进行复制,则行为未定义.
另外,请注意(7.21.6.5p2):
[...]因此,当且仅当返回值为非负且小于n时,才会完全写入以null结尾的输出.
也就是说,如果你的缓冲区是一个512的数组char
并且你传入了512,那么该字符串被正确写入并且如果返回n
值为*snprintf
is 则不被截断0 <= n <= 511
请注意,Microsoft Visual C++的名称非常破碎_vsnprintf
:
[...]如果要写入的字符数小于或等于count,则返回写入的字符数; 如果要写入的字符数大于count,则这些函数返回-1表示输出已被截断.
最后,如果您只编写Linux/Glibc特定代码,您还可以考虑使用vasprintf
它来动态分配足够大的缓冲区来保存整个字符串.
归档时间: |
|
查看次数: |
1510 次 |
最近记录: |