今天早上有同事说调用封装好的编码转换函数,有时候能转换成功,有时候转换会失败,一听现象我就猜测是用法导致的问题,定位下来果然是用法使用有误,当然也跟我们封装的函数有关,记录下来,避免再次采坑。
一,发现问题
该编码转换函数实现如下:
//ANSI转UTF8
static std::string AnsiToUtf8(const std::string &strAnsi)
{
std::wstring strUnicode = AnsiToUnicode(strAnsi);
return UnicodeToUTF8(strUnicode);
}
//UNICODE转UTF8
static std::string UnicodeToUTF8(const std::wstring& strUnicode)
{
int nUtf8Length = WideCharToMultiByte(CP_UTF8,
0,
strUnicode.c_str(),
-1,
NULL,
0,
NULL,
NULL);
char* pUtf8 = new char[nUtf8Length + 1];
memset((void*)pUtf8, 0, sizeof(char) * (nUtf8Length + 1));
::WideCharToMultiByte(CP_UTF8,
0,
strUnicode.c_str(),
-1,
pUtf8,
nUtf8Length,
NULL,
NULL);
std::string strUtf8;
strUtf8 = pUtf8;
delete[] pUtf8;
return strUtf8;
}
实现ANSI编码转换为utf8编码,函数返回值是一个局部变量std::string,该同事在外部调用的时候直接用const char* p = UnicodeToUTF8().c_str()来接收,可是c_str()就只是返回一个地址而已,而这个地址可能会随着string 对象的销毁(比如此处的局部对象)而变得无效!!
调用处的代码大概如下所示:
const char *p1 = AnsiToUtf8("你好").c_str();
std::string str3 = Utf8ToAnsi(p1);
此时调试发现这个指针p1的地址指向此时是一个无效值,同时调用Utf8ToAnsi将该utf8编码的字符串转换回来会发现转换失败。
而采用
std::string str1 = AnsiToUtf8("你好");
写法程序能够正常运行,这是因为使用了一个新的局部变量std::string str1来接收了函数的返回值,str1内部维护了一个新的内存。
二,解决方法
当初实现编码转换函数的时候,本意也是使用c++语言来调用的,使用std::string来接收返回值的,加上没有想到std::string的c_str()函数这个坑,导致此问题的出现。由于其他处的代码使用没有问题,暂时就修改该处使用不当的代码,并且在编码转换接口上写上备注,避免其他开发人员犯同样的错误。