說到TCHAR,大家應(yīng)該是不陌生雁佳。
TCHAR簡介
為什么會有TCHAR,因?yàn)镃++支持兩種字符集,如下:
- ANSI字符集:Multi-Byte Character
- Unicode字符集:Unicode Character
VS2008中字符集設(shè)置:
右鍵工程-“Properties”-“Configuration Properties”-“General”-“Character Set”厅瞎。
微軟baba為了統(tǒng)一這兩套編碼,所以有了TCHAR這個(gè)怪咖初坠,通過條件編譯(_UNICODE
宏和UNICODE
宏)控制實(shí)際使用的字符集和簸。
TCHAR詳細(xì)信息
-
Use Unicode Character Set,其定義如下:
typedef WCHAR TCHAR, *PTCHAR
其中WCHAR的定義為:typedef wchar_t WCHAR
-
Use Multi-Byte Character Set碟刺,其定義如下:
typedef char TCHAR, *PTCHAR
已知char類型長度為1個(gè)字節(jié)锁保,而wchar_t類型長度為2個(gè)字節(jié);
那么可知,TCHAR類型在Multi-Byte字符集下占1個(gè)字節(jié)身诺,在Unicode字符集下占2個(gè)字節(jié)蜜托。
同一個(gè)TCAHR類型的數(shù)組變量在不同字符集下,長度是不同的霉赡。
TCHAR ptszArray[10];
- 在Unicode字符集下橄务,長度為20個(gè)字節(jié)
- 在Multi-Byte字符集下,長度為10個(gè)字節(jié)
問題
扯了這么多閑話穴亏,說說正事
這次問題牽涉到一個(gè)dll和exe蜂挪,大致情況如下:
dll:Unicode字符集
exe:Multi-Byte字符集
exe加載dll后通過一個(gè)獲取函數(shù)列表接口獲取所有函數(shù)指針,該接口的參數(shù)為一個(gè)函數(shù)指針結(jié)構(gòu)體嗓化,大致如下:
typedef struct BLKFUNLISTTAG
{
TCHAR m_ptszDevName[10];
Fun1 m_pFun1;
Fun2 m_pFun2;
}BlkFunList, *pBlkFunList;
dll和exe中都是使用TCHAR數(shù)組棠涮,導(dǎo)致在dll中明明結(jié)構(gòu)體中的2個(gè)函數(shù)指針已經(jīng)被賦值;但是運(yùn)行到exe后刺覆,卻發(fā)現(xiàn)2個(gè)函數(shù)指針的值全為零严肪。WTF!!!
后來經(jīng)過分析,是TCHAR搗的鬼谦屑。
在dll中TCHAR實(shí)際上是wchar_t驳糯,則m_ptszDevName[10]的長度為20個(gè)字節(jié),而到了exe后氢橙,TCHAR實(shí)際上是char酝枢,其長度為10個(gè)字節(jié)。
假如DevName為"HID"悍手,由于dll為Unicode字符集帘睦,則其內(nèi)存信息如下:
\x00\x68\x00\x69\x00\x64\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
exe里拿到上面這段內(nèi)存地址,會按照char類型去解析坦康。則只會取前面10個(gè)字節(jié)的數(shù)據(jù):
\x00\x68\x00\x69\x00\x64\x00\x00\x00\x00
剩余的10個(gè)字節(jié)就會覆蓋結(jié)構(gòu)體后面的兩個(gè)函數(shù)指針成員竣付,最終導(dǎo)致2個(gè)函數(shù)指針的值為0。
哎涝焙,想想都覺得可怕卑笨。
解決方案
為了不影響dll和exe中現(xiàn)有代碼,所以只是將exe中結(jié)構(gòu)體定義中的m_ptszDevName的類型由TCHAR改為WCHAR仑撞。