一些信息:
当我运行它会发生什么
我得到期望的string“abcd”重复,直到它达到4094个字符的位置。 之后,它输出的是这个符号“?” 直到文件结束。
我怎么看这个?
我认为这不是预期的行为,它必须是一个错误的地方。
您可以testing的代码:
#include <iostream> #include <fstream> #include <locale> #include <codecvt> void createTestFile() { std::ofstream file ("utf16le.txt", std::ofstream::binary); if (file.is_open()) { uint16_t bom = 0xFEFF; // UTF-16 little endian BOM uint64_t abcd = 0x0064006300620061; // UTF-16 "abcd" string file.write((char*)&bom,2); for (size_t i=0; i<2000; i++) { file.write((char*)&abcd,8); } file.close(); } } int main() { //createTestFile(); // uncomment to make the test file std::wifstream file; std::wstring line; file.open("utf16le.txt"); file.imbue(std::locale(file.getloc(), new std::codecvt_utf16<wchar_t, 0x10ffff, std::consume_header>)); if (file.is_open()) { while (getline(file,line)) { std::wcout << line << std::endl; } } }
这看起来像一个库的bug。 按照gcc 7.1.1使用gdb
编译的示例程序:
(gdb) n 28 while (getline(file,line)) { (gdb) n 29 std::wcout << line << std::endl; (gdb) p line.size() $1 = 8000
如预期的那样,读取8000个字符。 但是之后:
(gdb) p line[4092] $18 = (__gnu_cxx::__alloc_traits<std::allocator<wchar_t> >::value_type &) @0x628240: 97 L'a' (gdb) p line[4093] $19 = (__gnu_cxx::__alloc_traits<std::allocator<wchar_t> >::value_type &) @0x628244: 98 L'b' (gdb) p line[4094] $20 = (__gnu_cxx::__alloc_traits<std::allocator<wchar_t> >::value_type &) @0x628248: 25344 L'挀' (gdb) p line[4095] $21 = (__gnu_cxx::__alloc_traits<std::allocator<wchar_t> >::value_type &) @0x62824c: 25600 L'搀' (gdb) p line[4096] $22 = (__gnu_cxx::__alloc_traits<std::allocator<wchar_t> >::value_type &) @0x628250: 24832 L'愀'
line[4092]
和line[4093]
看起来不错。 但是,我看到line[4094]
, line[4095]
和line[4096]
,包含6300
和6500
,而不是0063
和0065
。
所以,这实际上是从字符4094开始,而不是从4096开始。 我甩了二进制UTF-16文件,它看起来对我来说是正确的。 BOM标记后面是整个文件内容的一致性排序。
唯一令人困惑的是为什么clang和gcc都会受到影响,但Google的一个快速搜索表明,clang也使用gcc的libstdc ++,至少直到最近。 所以,这看起来像一个libstdc ++的bug。