CreateProcess 的陷阱

使用 CreateProcess 创建子进程时,需要特别注意的一点是 lpCommandLine 必须是可写的字符串缓冲区,不能传入字符串常量,否则程序会因尝试写入只读内存而在运行时直接崩溃。在使用主流的 C 语言编译器时,编译器不会对此进行检查,而 C++ 编译器在编译时会发出警告。

CreateProcessACreateProcessW 的函数原型如下所示:

BOOL CreateProcessA(
  [in, optional]      LPCSTR                lpApplicationName,
  [in, out, optional] LPSTR                 lpCommandLine,
  [in, optional]      LPSECURITY_ATTRIBUTES lpProcessAttributes,
  [in, optional]      LPSECURITY_ATTRIBUTES lpThreadAttributes,
  [in]                BOOL                  bInheritHandles,
  [in]                DWORD                 dwCreationFlags,
  [in, optional]      LPVOID                lpEnvironment,
  [in, optional]      LPCSTR                lpCurrentDirectory,
  [in]                LPSTARTUPINFOA        lpStartupInfo,
  [out]               LPPROCESS_INFORMATION lpProcessInformation
);

BOOL CreateProcessW(
  [in, optional]      LPCWSTR               lpApplicationName,
  [in, out, optional] LPWSTR                lpCommandLine,
  [in, optional]      LPSECURITY_ATTRIBUTES lpProcessAttributes,
  [in, optional]      LPSECURITY_ATTRIBUTES lpThreadAttributes,
  [in]                BOOL                  bInheritHandles,
  [in]                DWORD                 dwCreationFlags,
  [in, optional]      LPVOID                lpEnvironment,
  [in, optional]      LPCWSTR               lpCurrentDirectory,
  [in]                LPSTARTUPINFOW        lpStartupInfo,
  [out]               LPPROCESS_INFORMATION lpProcessInformation
);
#include <Windows.h>

int main()
{
    // 错误:传入字符串常量,运行时会崩溃
    BOOL bSuccess = CreateProcessW(
        NULL,
        L"C:/Windows/System32/notepad.exe",
        NULL,
        NULL,
        FALSE,
        0,
        NULL,
        NULL,
        NULL,
        NULL
    );
    // 正确:使用可写的字符串缓冲区
    wchar_t cmd[] = L"C:/Windows/System32/notepad.exe";
    bSuccess = CreateProcessW(
        NULL,
        cmd,
        NULL,
        NULL,
        FALSE,
        0,
        NULL,
        NULL,
        NULL,
        NULL
    );
}
clang 和 clang++ 编译对比
clangclang++ 编译对比