慎用USES_CONVERSION

慎用USES_CONVERSION

慎用USES_CONVERSION

USES_CONVERSION是ATL中的一个宏定义。用于编码转换(用的比较多的是CString向LPCWSTR转换)。在ATL下使用要包含头文件#include "atlconv.h"

使用USES_CONVERSION一定要小心,它们从堆栈上分配内存,直到调用它的函数返回,该内存不会被释放。如果在一个循环中,这个宏被反复调用几万次,将不可避免的产生stackoverflow。

 

在一个函数的循环体中使用A2W等字符转换宏可能引起栈溢出。

#include  < atlconv.h >
void  fn()
{
    
while ( true )
    {
        {
            USES_CONVERSION;
            DoSomething(A2W(
" SomeString " ));
        }
    }
}

让我们来分析以上的转换宏

#define  A2W(lpa) (\
   ((_lpa 
=  lpa)  ==  NULL)  ?  NULL : (\
      _convert 
=  (lstrlenA(_lpa) + 1 ),\
      ATLA2WHELPER((LPWSTR) alloca(_convert
* 2 ), _lpa, _convert)))
#define  ATLA2WHELPER AtlA2WHelper
inline LPWSTR WINAPI AtlA2WHelper(LPWSTR lpw, LPCSTR lpa, 
int  nChars, UINT acp)
{
   ATLASSERT(lpa 
!=  NULL);
   ATLASSERT(lpw 
!=  NULL);
   
//  verify that no illegal character present
   
//  since lpw was allocated based on the size of lpa
   
//  don't worry about the number of chars
   lpw[ 0 =   ' \0 ' ;
   MultiByteToWideChar(acp, 
0 , lpa,  - 1 , lpw, nChars);
   
return  lpw;
}

关键的地方在 alloca  内存分配内存上。

#define  alloca  _alloca

_alloca
Allocates memory on the stack.

Remarks
_alloca allocates size bytes from the program stack. The allocated space is automatically freed when the calling function

exits. Therefore, do not pass the pointer value returned by _alloca as an argument to free.

问题就在这里,分配的内存是在函数的栈中分配的。而VC编译器默认的栈内存空间是2M。当在一个函数中循环调用它时就会不断的分配栈中的内存。

以上问题的解决办法:
1、自己写字符转换函数,不要偷懒

Function that safely converts a  ' WCHAR '  String to  ' LPSTR ' :
char *  ConvertLPWSTRToLPSTR (LPWSTR lpwszStrIn)
{
  LPSTR pszOut 
=  NULL;
  
if  (lpwszStrIn  !=  NULL)
  {
 
int  nInputStrLen  =  wcslen (lpwszStrIn);
 
//  Double NULL Termination
  int  nOutputStrLen  =  WideCharToMultiByte (CP_ACP,  0 , lpwszStrIn, nInputStrLen, NULL,  0 0 0 +   2 ;
 pszOut 
=   new   char  [nOutputStrLen];
 
if  (pszOut)
 {
   memset (pszOut, 
0x00 , nOutputStrLen);
   WideCharToMultiByte(CP_ACP, 
0 , lpwszStrIn, nInputStrLen, pszOut, nOutputStrLen,  0 0 );
 }
  }
  
return  pszOut;
}

等等一个一个的实现。

2、把字符转换部分放到一个函数中处理。

void  fn2()
{
    USES_CONVERSION;
    DoSomething(A2W(
" SomeString " ));
}
void  fn()
{
    
while ( true )
    {
        fn2();
    }
}

如果不知道这点问题,在使用后崩溃时很难查出崩溃原因的。


转自: http://www.cnblogs.com/carekee/articles/1935789.html 

你可能感兴趣的:(慎用USES_CONVERSION)