首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> 關於C

C語言陷阱:Unicode 編譯下 CreateProcess 參數類型不匹配導致崩潰

     編輯:關於C

從 MSDN 複製的 C 代碼調用 CreateProcess 啟動計算器,Unicode 編譯下編譯通過但運行崩潰,C++ 編譯直接報錯。根因是字符串字面量類型與 API 要求不匹配。

問題代碼

// test.c - Unicode 編譯
#include 
void 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);
}

編譯器警告/錯誤

  • C 編譯器 (Unicode):warning C4133: 'function' : incompatible types - from 'char [9]' to 'LPWSTR' —— 只警告,編譯通過,運行時傳入錯誤指針導致崩潰。
  • C++ 編譯器:error C2664: 'CreateProcessW' : cannot convert parameter 2 from 'const char [9]' to 'LPWSTR' —— 直接報錯,阻攔錯誤代碼生成。

根因分析

  1. Unicode 編譯下 CreateProcess 宏展開為 CreateProcessW,第二參數類型為 LPWSTR(wchar_t*)。
  2. "calc.exe" 是窄字符串 char[9],C 允許隱式轉換為 void* 再隱式轉為 LPWSTR(僅警告),實際傳入的是 ANSI 字符串地址,但函數按寬字符解讀 → 訪問越界/無效內存 → 崩潰。
  3. C++ 類型檢查嚴格,禁止窄字符串隱式轉寬字符指針,直接報錯。

正確寫法(三種)

1. 顯式寬字符串字面量

L"calc.exe" // 類型 const wchar_t[],匹配 LPWSTR(需去 const)

2. 使用 _T / TEXT 宏(推薦,適配 ANSI/Unicode 雙模式)

_T("calc.exe") // 定義 _UNICODE 時展開為 L"calc.exe",否則 "calc.exe"

3. 顯式轉換(不推薦,僅作理解)

(LPWSTR)L"calc.exe" // 強制類型轉換,掩蓋錯誤而非修正

最佳實踐

  • Windows API 開發統一使用 _T/TEXT 宏包裹所有字符串字面量。
  • 項目屬性中明確設置字符集(Unicode/多字節),代碼配合宏自動適配。
  • C++ 編譯器更嚴格,建議重命名為 .cpp 甚至純 C++ 開發,盡早暴露類型錯誤。
  • 啟用最高警告等級 (/Wall 或 /W4),將警告視為錯誤 (/WX)。

總結

這是 C 語言弱類型指針轉換與 Windows 雙字符集機制交互產生的經典坑。字符串字面量必須與 API 期望的字符集匹配,善用 _T() 宏是跨字符集編程的基礎紀律。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved