最近做了一个COM组件负责socket通讯,发现一个无法解决的问题,当socket发送较慢(当连一个代理服务器发送时通常会慢一些),COM组件提供的接口函数中将BSTR转换为char*时会造成程序崩溃,具体异常是操作了受保护的内存之类,跟踪代码发现出问题的代码为:_com_util::ConvertBSTRToString,这是微软提供标准转换代码,心灰意冷,以为这个问题绕不过去了。
后来无意间google到下面这篇文章,原来别人也发现了微软该函数的bug,就是函数内内存申请的问题,作者修复完的函数如下:
//implement our own conversion functions
//------------------------//
// Convert char * to BSTR //
//------------------------//
inline BSTR ConvertStringToBSTR(const char* pSrc)
{
if(!pSrc) return NULL;
DWORD cwch;
BSTR wsOut(NULL);
if(cwch = ::MultiByteToWideChar(CP_ACP, 0, pSrc,
-1, NULL, 0))//get size minus NULL terminator
{
cwch--;
wsOut = ::SysAllocStringLen(NULL, cwch);
if(wsOut)
{
if(!::MultiByteToWideChar(CP_ACP,
0, pSrc, -1, wsOut, cwch))
{
if(ERROR_INSUFFICIENT_BUFFER == ::GetLastError())
return wsOut;
::SysFreeString(wsOut);//must clean up
wsOut = NULL;
}
}
};
return wsOut;
};
//------------------------//
// Convert BSTR to char * //
//------------------------//
inline char* ConvertBSTRToString(BSTR pSrc)
{
if(!pSrc) return NULL;
//convert even embeded NULL
DWORD cb,cwch = ::SysStringLen(pSrc);
char *szOut = NULL;
if(cb = ::WideCharToMultiByte(CP_ACP, 0,
pSrc, cwch + 1, NULL, 0, 0, 0))
{
szOut = new char[cb];
if(szOut)
{
szOut[cb - 1] = '\0';
if(!::WideCharToMultiByte(CP_ACP, 0,
pSrc, cwch + 1, szOut, cb, 0, 0))
{
delete []szOut;//clean up if failed;
szOut = NULL;
}
}
}
return szOut;
};
原文链接:
http://www.codeproject.com/Articles/1969/BUG-in-_com_util-ConvertStringToBSTR-and-_com_util