gpt4 book ai didi

c++ - swprintf 截断导致意外输出

转载 作者:搜寻专家 更新时间:2023-10-31 00:51:37 25 4
gpt4 key购买 nike

我正在修复在 linux 和 windows 上运行的遗留代码,在某些情况下,本应包含格式化内容的缓冲区小于该内容。

代码使用根据 documentation 的 swprintf

size - up to size - 1 characters may be written, plus the null terminator

确实会截断字符串,但在 coliru 上尝试时我遇到了意想不到的结果:

#include <iostream> 
#include <string>
#include <cwchar>

int main()
{

wchar_t wide[5];

std::swprintf(wide, sizeof wide/sizeof *wide, L"%ls", L"111111111");

std::wcout << wide;
}

将导致 1111?? 但是

#include <iostream> 
#include <string>
#include <cwchar>

int main()
{

wchar_t wide[20];

std::swprintf(wide, sizeof wide/sizeof *wide, L"%ls", L"111111111");

std::wcout << wide;
}

工作正常。

怎么了?

附言我希望我可以将所有内容更改为 C++ 流/字符串,但我不能,wchar_t 数组无处不在

最佳答案

tl;dr:出于某种原因,那些空终止语义取决于函数调用的成功,对于 swprintf 仅当缓冲区 足够大时它才会成功。因此,您第一次尝试的数组不是以 null 结尾的。


这很微妙,但 swprintfsnprintf 不同。它不会写入“至多 N-1 个字符”并认为在所有情况下都是成功的。

下面是同一文档中关于 swprintf 的返回值的内容:

Return value: Number of wide characters written (not counting the terminating null wide character) if successful or negative value if an encoding error occurred or if the number of characters to be generated was equal or greater than size (including when size is zero)

事实上,your attempt returns -1 .

由此(以及引用下方的注释)我们可以确定,如果提供的输出缓冲区中没有足够的字节,swprintf 将操作视为失败 .它不会溢出该缓冲区,但它也可能无法完成其工作,并且其工作包括编写 NULL 终止符。如果没有 NULL 终止符,您 [有效] 传递给 std::wcoutwchar_t* 将越界并且您的程序具有未定义的行为。


我承认,在随意阅读时,这似乎与 size 参数的语义相矛盾,C11 对此声明:

No more than n wide characters are written, including a terminating null wide character, which is always added (unlessn is zero).

…没有说明函数调用是否成功的任何条件。

可以将此称为标准中的编辑缺陷或实现错误。 但是即使两者都不是真的,您的函数调用也被视为不成功,我认为您不应该依赖相应的结果。

我们至少可以看到 libc 意图与上面的破败相匹配,来自 this manual page on Formatted Output Functions :

The return value is the number of characters generated for the given input, excluding the trailing null. If not all output fits into the provided buffer a negative value is returned. You should try again with a bigger output string. Note: this is different from how snprintf handles this situation.


您将不得不注意上述注意事项:

While narrow strings provide std::snprintf, which makes it possible to determine the required output buffer size, there is no equivalent for wide strings, and in order to determine the buffer size, the program may need to call std::swprintf, check the result value, and reallocate a larger buffer, trying again until successful.

...或者完全切换到其他一些功能。

关于c++ - swprintf 截断导致意外输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54544738/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com