MFC/ATL/COM 開發中,BSTR (COM 字串)、char*/wchar_t* (C 風格)、CString (MFC 字串)、_bstr_t、_variant_t (智慧封裝) 五種字串類型頻繁互轉。本文提供完整轉換對照表、程式碼範例與記憶體管理注意事項,解決亂碼、洩漏、存取違規等常見問題。
| 類型 | 本質 | 記憶體管理 | 適用場景 |
|---|---|---|---|
BSTR | 長度前綴 + 寬字元 + 雙重 NULL 結尾 | SysAllocString/SysFreeString 手動管理 | COM 介面參數、ActiveX、Office 自動化 |
char* / wchar_t* | C 風格字串 | malloc/free、new/delete[]、靜態緩衝區 | C API、舊式庫、網路封包 |
CString (MFC/ATL) | 參考計數、COW、自動轉換 ANSI/Unicode | 自動 (析構釋放) | MFC/ATL 專案通用字串 |
_bstr_t | BSTR 智慧指標 (RAII) | 建構/複製/指派自動 SysAllocString,析構 SysFreeString | COM 程式碼簡化 BSTR 管理 |
_variant_t | VARIANT 智慧封裝 | 自動 VariantInit/Clear | 自動化介面、資料庫欄位值 |
// 1. char* → CString
CString cs = "hello"; // 直接賦值 (編譯器自動轉換)
cs.Format(_T("%s"), pszAnsi); // 格式化
// 2. CString → char* (需注意編碼)
LPSTR psz = cs.GetBuffer(); // 取得內部緩衝區指標 (可修改)
cs.ReleaseBuffer(); // 必須配對釋放
// 或複製一份
char* pszCopy = _strdup(cs.GetString()); // 需 free()
// 3. BSTR ↔ char*
#include
#pragma comment(lib, "comsupp.lib")
BSTR bstr = SysAllocString(L"Test");
char* psz = _com_util::ConvertBSTRToString(bstr); // 需 delete[] psz
SysFreeString(bstr);
// _bstr_t 最簡單
_bstr_t bt = bstr; // BSTR → _bstr_t
char* psz2 = bt; // _bstr_t → char* (自動轉換)
BSTR bstr2 = _bstr_t("Test"); // char* → BSTR
// 4. CString ↔ BSTR
BSTR bstr3 = cs.AllocSysString(); // CString → BSTR (需 SysFreeString)
CString cs2(bstr3); // BSTR → CString (直接建構)
// 5. _variant_t 通吃
_variant_t var = "Test";
BSTR bstr4 = var.bstrVal; // 取得 BSTR (variant 內部管理,勿手動 Free)
var = bstr4; // BSTR → _variant_t
// 6. ANSI/Unicode/寬字元 宏轉換 (ATL 7.0+)
#include
USES_CONVERSION;
LPCWSTR wsz = A2W(pszAnsi); // ANSI → 寬字元 (堆疊緩衝區)
LPSTR pszAnsi2 = W2A(wsz); // 寬字元 → ANSI
// 大緩衝區版:CA2WEX<1024>, CW2AEX<1024>
SysAllocString → SysFreeString;_com_util::ConvertBSTRToString → delete[];_strdup → free。_bstr_t、_variant_t、CComBSTR (ATL) 自動管理生命週期,極大減少洩漏。CA2WEX/CW2AEX 指定緩衝區大小。| 錯誤現象 | 原因 | 修正 |
|---|---|---|
| BSTR 內容截斷/亂碼 | 含有內嵌 NULL,BSTR 以長度為準非 NULL 結尾 | 使用 SysStringLen 取得真實長度 |
| CString 給 COM 介面後內容被修改 | 傳遞 CString::GetBuffer() 導致緩衝區暴露 | 改用 AllocSysString() 複製一份 BSTR |
| _bstr_t 指派後原 BSTR 失效 | _bstr_t 指派會 SysFreeString 舊值 | 理解 RAII 語意,若需共享用 BSTR* 或 CComBSTR |
| Debug/Release 行為不一致 | 未初始化緩衝區、配置/釋放不配對 | 全面啟用 /RTC1、使用智慧指標 |
掌握上述轉換模式與管理規則,COM/MFC 字串處理將不再是 Bug 溫床。