[轉]有關USES_CONVERSION

轉自:http://blog.csdn.net/p40614021/article/details/6778100ide

 

ATL:轉換宏是各類字符編碼之間進行轉換的一種很方便的方式,在函數調用時,它們顯得很是有用。ATL轉換宏的名稱是根據下面的模式來命名的[源類型]2[新類型]或者[源類型]2C[新類型]。據有第二種形式的名字的宏的轉換結果是常量指針(對應名字中的"C")。函數

爲了使用這些宏,須要先包含atlconv.h頭文件。你甚至能夠在非ATL工程中包含這個頭文件來使用其中定義的宏,由於這個頭文件獨立於ATL 中的其餘部分,不須要一個_Module全局變量。當你在一個函數中使用轉換宏時,須要把USES_CONVERSION宏放在函數的開頭。它定義了轉換 宏所需的一些局部變量編碼

在   mfc   下使用要包含     afxconv.h  
  atl   下是   atlconv.h  
  -------------  
  調用   USES_CONVERSION;   以後就可使用   OLE2T   等轉換的宏spa

 

例子 :.net

 

Unicode 字符集下的CString轉char*指針

 

 #include   <AFXCONV.H>   code

   

  CString   strUnicode(_T("unicode   string"));   orm

  USES_CONVERSION;   blog

  char*   pszChar   =   W2A(strUnicode));內存

 

可是!!慎用 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。當在一個函數中循環調用它時就會不斷的分配棧中的內存。

以上問題的解決辦法:
一、本身寫字符轉換函數,不要偷懶
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;
}
等等一個一個的實現。

二、把字符轉換部分放到一個函數中處理。

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

void fn()
{
    while(true)
    {
        fn2();
    }
}

若是不知道這點問題,在使用後崩潰時很難查出崩潰緣由的。

相關文章
相關標籤/搜索