從 MSDN 複製的 C 代碼調用 CreateProcess 啟動計算器,Unicode 編譯下編譯通過但運行崩潰,C++ 編譯直接報錯。根因是字符串字面量類型與 API 要求不匹配。
// test.c - Unicode 編譯 #includevoid main() { STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); ZeroMemory(&pi, sizeof(pi)); if (!CreateProcess( NULL, // lpApplicationName "calc.exe", // lpCommandLine - 這裡是 char[9] NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) return; WaitForSingleObject(pi.hProcess, INFINITE); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); }
warning C4133: 'function' : incompatible types - from 'char [9]' to 'LPWSTR' —— 只警告,編譯通過,運行時傳入錯誤指針導致崩潰。error C2664: 'CreateProcessW' : cannot convert parameter 2 from 'const char [9]' to 'LPWSTR' —— 直接報錯,阻攔錯誤代碼生成。CreateProcess 宏展開為 CreateProcessW,第二參數類型為 LPWSTR(wchar_t*)。"calc.exe" 是窄字符串 char[9],C 允許隱式轉換為 void* 再隱式轉為 LPWSTR(僅警告),實際傳入的是 ANSI 字符串地址,但函數按寬字符解讀 → 訪問越界/無效內存 → 崩潰。L"calc.exe" // 類型 const wchar_t[],匹配 LPWSTR(需去 const)
_T("calc.exe") // 定義 _UNICODE 時展開為 L"calc.exe",否則 "calc.exe"
(LPWSTR)L"calc.exe" // 強制類型轉換,掩蓋錯誤而非修正
.cpp 甚至純 C++ 開發,盡早暴露類型錯誤。/Wall 或 /W4),將警告視為錯誤 (/WX)。這是 C 語言弱類型指針轉換與 Windows 雙字符集機制交互產生的經典坑。字符串字面量必須與 API 期望的字符集匹配,善用 _T() 宏是跨字符集編程的基礎紀律。