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