为什么在Windows上打印这个宽字符字符串会崩溃?

3

我在进行一些单元测试时遇到了一个问题,以下简单的例子在使用sprintf的那一行崩溃,但我不确定原因是什么。(使用Windows和Visual Studio 2019)

#include <stdio.h>
#include <locale.h>

int main()
{
    setlocale(LC_ALL, "en_US.utf8");
    char output[255];
    sprintf(output, "simple %ls text", L"\u00df\U0001d10b");
    return 0;
}

代码有问题吗?


你有检查 setlocale 的返回值吗? - Andreas Wenzel
@AndreasWenzel 我刚刚做了,它是“en_US.utf8”。 - Julius
@AndreasWenzel 我强烈认为它是一个有效的字符,因为无效的字符似乎会导致编译错误。 - Julius
我无法真正回答这个问题,但是这可能会有所帮助:int n = snprintf(output, 254, "simple %ls text", L"\u00df\U0001d10b"); 返回值为12,并将 simple ßß 放入字符串中(省略了 text 部分)。 - Adrian Mole
4
这是一个错误。根本问题是sprintf实现使用wctomb_s()逐个转换字符。该函数存在一个错误,不能按设计正确地转换utf16代理项,并且应返回EILSEQ。它没有这样做,返回0并报告复制了-1个字节,导致堆栈溢出。一个适当的解决方法是切换到c16rtomb()并确保应用了C-11缺陷报告。同时,您将不得不自己处理这个bug。 - Hans Passant
显示剩余4条评论
1个回答

0

char 是 8 位的,而 wchar_t 是 16 位的。当你尝试转换这两种类型时,你需要使用像 MultiByteToWideChar 这样的函数来进行转换。

当你尝试在多字节函数中使用 Unicode 字符串时,会导致缓冲区溢出,这可能是你崩溃的原因。

尝试使用 swprintf_s 替代。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接