使用wstring_convert转换TTF字体Name ID19字符串时崩溃问题
问题:处理seguiemj.ttf字体Name ID 19字符串时编码转换崩溃原因
尝试对seguiemj.ttf字体“name”表中Name ID 19指向的字符串进行编码转换操作,其他字符串处理均正常,但运行提供的C++代码时,converterUtf8.to_bytes(u16str)代码段发生崩溃,希望了解该问题的原因。
提供的代码如下:
#include <iostream> #include <vector> #include <string> #include <cstring> #include <codecvt> #include <memory> #include <locale> #include <utility> int main() { std::vector<unsigned char> data = { 0xD8, 0x3D, 0xDE, 0x02, 0xD8, 0x3D, 0xDE, 0x0D, 0xD8, 0x3D, 0xDE, 0x2D, 0xD8, 0x3D, 0xDC, 0x81, 0xD8, 0x3D, 0xDC, 0x4D, 0xD8, 0x3D, 0xDC, 0x8B, 0xD8, 0x3D, 0xDC, 0x31, 0xD8, 0x3E, 0xDD, 0x89, 0xD8, 0x3C, 0xDF, 0x3A, 0xD8, 0x3C, 0xDF, 0x32, 0xD8, 0x3C, 0xDF, 0x53, 0xD8, 0x3C, 0xDF, 0x55, 0xD8, 0x3C, 0xDF, 0x82, 0xD8, 0x3C, 0xDF, 0xF0, 0xD8, 0x3C, 0xDF, 0xE0, 0xD8, 0x3D, 0xDE, 0x84, 0xD8, 0x3D, 0xDE, 0x92, 0xD8, 0x3D, 0xDE, 0xEB, 0xD8, 0x3D, 0xDE, 0xCD }; std::cout << data.size() << std::endl; std::wstring_convert<std::codecvt_utf16<char16_t>, char16_t> converter; const std::u16string u16str = converter.from_bytes( reinterpret_cast<const char*>(data.data()), reinterpret_cast<const char*>(data.data() + data.size()) ); std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> converterUtf8; std::string nameString = converterUtf8.to_bytes(u16str); std::cout << nameString << std::endl; return 0; }
崩溃原因分析
无效UTF-16序列触发转换错误:
你提供的data字节数组中,所有数据都是UTF-16的高代理项(比如0xD83D、0xD83C这类),但没有对应的低代理项。std::codecvt_utf16<char16_t>的from_bytes方法仅做简单的字节转char16_t操作,不会校验序列合法性;但std::codecvt_utf8_utf16<char16_t>的to_bytes要求输入必须是合法的UTF-16序列——要么是单个BMP范围内的字符,要么是成对的高+低代理项。单独的高代理项属于非法序列,转换时会触发内部断言或未定义行为,直接导致程序崩溃。字体Name ID 19的特殊存储规则:
seguiemj.ttf是微软的emoji专用字体,其Name ID 19的字符串并非标准UTF-16编码,而是存储了emoji字符对应的UTF-16高代理项的单独部分。这种存储是字体内部的特殊设计,不遵循通用UTF编码规范,标准编码转换工具无法处理这类非标准格式,因此会出错。
内容的提问来源于stack exchange,提问作者nothing_hooooo
相关产品推荐
相关产品推荐

