FormatMessage返回含空字符分隔的char*?问题排查与修复咨询
FormatMessage返回字符串字符间有空字符的修复方案
问题描述
调用FormatMessage获取系统错误消息时,返回的字符串指针pMsgBuf内容呈现为"T\0h\0e\0 \0s\0r\0a\0...."格式——消息内容完整,但每个字符之间被空字符分隔。虽然通过循环过滤空字符能得到正确结果,但希望从参数层面彻底解决问题。
原因分析
代码存在类型不匹配的核心问题:
- 声明了
char* pMsgBuf来接收结果,但调用FormatMessage时强制将其转换为LPWSTR(宽字符指针)。 - 当FormatMessage以宽字符模式(默认启用UNICODE宏时的行为)运行时,会分配UTF-16编码的宽字符缓冲区,每个字符占用2字节。对于ASCII范围内的字符,高字节为0,因此用
char*读取时,就会看到字符间夹着空字符。 - 原代码中
std::string errorString = pMsgBuf会直接被第一个空字符截断,无法得到完整消息;sizeof(pMsgBuf)仅获取指针本身的大小,属于无效代码。
修复方案
方案1:显式调用ANSI版本FormatMessageA
直接调用FormatMessageA,让系统分配ANSI编码的单字节缓冲区,无需额外转换:
char* pMsgBuf = nullptr; const DWORD nMsgLen = FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<LPSTR>(&pMsgBuf), 0, nullptr ); if (nMsgLen == 0) { return "Unidentified error code"; } std::string errorString(pMsgBuf); LocalFree(pMsgBuf); return errorString;
方案2:使用宽字符流程处理
保持宽字符输出,再转换为std::string(适合需要处理非ASCII字符的场景):
wchar_t* pMsgBuf = nullptr; const DWORD nMsgLen = FormatMessageW( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<LPWSTR>(&pMsgBuf), 0, nullptr ); if (nMsgLen == 0) { return "Unidentified error code"; } // 稳妥转换宽字符到多字节字符串 int bufferSize = WideCharToMultiByte(CP_UTF8, 0, pMsgBuf, nMsgLen, nullptr, 0, nullptr, nullptr); std::string errorString(bufferSize, 0); WideCharToMultiByte(CP_UTF8, 0, pMsgBuf, nMsgLen, &errorString[0], bufferSize, nullptr, nullptr); LocalFree(pMsgBuf); return errorString;
内容的提问来源于stack exchange,提问作者Clark Dixon
相关产品推荐
相关产品推荐

