最近做了一个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