iooiau.net

CreateProcess() の罠

CreateProcess() 関数はプロセスの起動に使われますが、いやらしい罠があります。
よく API の解説などで以下のようなコードが掲載されています。


STARTUPINFO si;
PROCESS_INFORMATION pi;

ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));

if (!CreateProcess(NULL,
                   TEXT("Notepad.exe"),  // メモ帳を起動
                   NULL,
                   NULL,
                   FALSE,
                   0,
                   NULL,
                   NULL,
                   &si,
                   &pi)) {
    return;
}

CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);

しかし、このコードは間違っています
それは関数の定義を見れば分かります。以下は CreateProcess() 関数の定義です。


BOOL WINAPI CreateProcess(
  LPCTSTR lpApplicationName,
  LPTSTR lpCommandLine,
  LPSECURITY_ATTRIBUTES lpProcessAttributes,
  LPSECURITY_ATTRIBUTES lpThreadAttributes,
  BOOL bInheritHandles,
  DWORD dwCreationFlags,
  LPVOID lpEnvironment,
  LPCTSTR lpCurrentDirectory,
  LPSTARTUPINFO lpStartupInfo,
  LPPROCESS_INFORMATION lpProcessInformation
);

最初の二つの引数を見比べてみてください。
そう、型が違います
1番目の引数は LPCTSTR ですが、2番目の引数は LPTSTR です。
2番目の引数に C が付いていないということは、書き換え可能なバッファを渡さなければいけないのです。
文字列定数は通常、(コンパイラの設定によりますが)書き換えできない領域に置かれます。
つまり上記のようなコードを書くと、OS によってはアクセス違反で強制終了となります。