gcc/g++ 给我报错 "CreateProcess: No such file or directory"

9
-编辑- 看起来存在路径问题,无法找到其bin/文件夹。尽管g++在该bin目录中。
我正在尝试在Windows应用程序中启动g++,但是我遇到了下面的错误。如何修复?顺便说一句,在提示符中我可以轻松执行g++ dummy.cpp
参数 -o file.exe -x c++ - 标准输出
: CreateProcess: No such file or directory

-编辑- 我的代码是...

#include <windows.h> 
#include <stdio.h> 
#include <strsafe.h>

#include <ios>
#include <iostream>
#include <fstream>
#include <sstream>
#include <exception>
#include <string>
#include <deque>
#include <stdio.h>
#include <stdlib.h>

using namespace std;

string gcc_bin="E:/dev/external/MinGW/bin/g++.exe";
string gcc_folder="E:/dev/external/MinGW/bin/";

int launch_gcc(ostringstream&o);
int main(){
    ostringstream osz;
    osz << "#include <cstdio>" << endl << "int main(){ printf(\"hello\"); } return 4; }";
    {
        launch_gcc(osz);
    }
    return 0;
}





void ErrorExit(PTSTR);
int launch_gcc(ostringstream&o)
{

    char buf2[4096];
char buf[4096];
ExpandEnvironmentStrings("%PATH%", buf, 4095);
OutputDebugString(buf);

    sprintf(buf2, "PATH=%s;%s;\0\0", gcc_folder.c_str(), buf);

    STARTUPINFO startupInfo;
    PROCESS_INFORMATION processInformation;

    HANDLE g_hChildStd_IN_Rd = NULL;
    HANDLE g_hChildStd_IN_Wr = NULL;
    HANDLE g_hChildStd_OUT_Rd = NULL;
    HANDLE g_hChildStd_OUT_Wr = NULL;
    HANDLE g_hChildStd_ERR_Rd = NULL;
    HANDLE g_hChildStd_ERR_Wr = NULL;

    HANDLE g_hInputFile = NULL;

    SECURITY_ATTRIBUTES saAttr;  
    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
    saAttr.bInheritHandle = TRUE; 
    saAttr.lpSecurityDescriptor = NULL; 

    if ( ! CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0) ) 
    ErrorExit(TEXT("StdoutRd CreatePipe")); 
    if ( ! SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0) )
    ErrorExit(TEXT("Stdout SetHandleInformation"));

    if ( ! CreatePipe(&g_hChildStd_ERR_Rd, &g_hChildStd_ERR_Wr, &saAttr, 0) ) 
    ErrorExit(TEXT("StderrRd CreatePipe")); 
    if ( ! SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0) )
    ErrorExit(TEXT("Stderr SetHandleInformation"));

    if (! CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0)) 
    ErrorExit(TEXT("Stdin CreatePipe")); 
    if ( ! SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0) )
    ErrorExit(TEXT("Stdin SetHandleInformation")); 

    ZeroMemory( &startupInfo, sizeof(STARTUPINFO) );
    startupInfo.cb = sizeof(STARTUPINFOA); 
    startupInfo.hStdError = g_hChildStd_OUT_Wr;
    startupInfo.hStdOutput = g_hChildStd_ERR_Wr;
    startupInfo.hStdInput = g_hChildStd_IN_Rd;
    startupInfo.dwFlags |= STARTF_USESTDHANDLES;

    ZeroMemory( &processInformation, sizeof(PROCESS_INFORMATION) );

    bool bSuccess = CreateProcess(
        gcc_bin.c_str(),
        " -o \"c:/dev/src/git/myprj/theout.exe\" -x c++ -",
0,
  0,
  1,
  NORMAL_PRIORITY_CLASS,
  0,//buf2,
  0,//gcc_folder.c_str(),
  &startupInfo,
  &processInformation
);
   if ( ! bSuccess ) 
      ErrorExit(TEXT("CreateProcess"));
   else 
   {
      // Close handles to the child process and its primary thread.
      // Some applications might keep these handles to monitor the status
      // of the child process, for example. 

      CloseHandle(processInformation.hProcess);
      CloseHandle(processInformation.hThread);
   }


    { 
    DWORD dwRead, dwWritten; 
    BOOL bSuccess = FALSE;

    auto sz=o.str();
    bSuccess = WriteFile(g_hChildStd_IN_Wr, sz.c_str(), sz.size(), &dwWritten, NULL);
    //if ( ! bSuccess ) break; 

    if ( ! CloseHandle(g_hChildStd_IN_Wr) ) 
        ErrorExit(TEXT("StdInWr CloseHandle")); 
    } 



    #define BUFSIZE 1024*4
    { 
    DWORD dwRead, dwWritten; 
    CHAR chBuf[BUFSIZE]; 
    BOOL bSuccess = FALSE;
    HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE);

    chBuf[0]=0;
    if (!CloseHandle(g_hChildStd_OUT_Wr)) 
        ErrorExit(TEXT("StdOutWr CloseHandle")); 

    for (;;) 
    { 
        bSuccess = ReadFile( g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL);
        if( ! bSuccess || dwRead == 0 ) break; 

        bSuccess = WriteFile(hParentStdOut, chBuf, 
                            dwRead, &dwWritten, NULL);
        chBuf[dwWritten]=0;
        if (! bSuccess ){ 
            printf("%s", chBuf);
            break; 
        }
    } 
    }

    { 
    DWORD dwRead, dwWritten; 
    CHAR chBuf[BUFSIZE]; 
    BOOL bSuccess = FALSE;
    HANDLE hParentStdErr = GetStdHandle(STD_ERROR_HANDLE);

    if (!CloseHandle(g_hChildStd_ERR_Wr)) 
        ErrorExit(TEXT("StdOutWr CloseHandle")); 

    for (;;) 
    { 
        bSuccess = ReadFile( g_hChildStd_ERR_Rd, chBuf, BUFSIZE, &dwRead, NULL);
        if( ! bSuccess || dwRead == 0 ) break; 

        bSuccess = WriteFile(hParentStdErr, chBuf, 
                            dwRead, &dwWritten, NULL);
        chBuf[dwWritten]=0;
        if (! bSuccess ){ 
            printf("%s", chBuf);
            break; 
        }
    }
    auto a=1;
    }


    return 0;
}

void ErrorExit(PTSTR lpszFunction) 
{ 
    LPVOID lpMsgBuf;
    LPVOID lpDisplayBuf;
    DWORD dw = GetLastError(); 

    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER | 
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        dw,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR) &lpMsgBuf,
        0, NULL );

    lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, 
        (lstrlen((LPCTSTR)lpMsgBuf)+lstrlen((LPCTSTR)lpszFunction)+40)*sizeof(TCHAR)); 
    StringCchPrintf((LPTSTR)lpDisplayBuf, 
        LocalSize(lpDisplayBuf) / sizeof(TCHAR),
        TEXT("%s failed with error %d: %s"), 
        lpszFunction, dw, lpMsgBuf); 
    MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK); 

    LocalFree(lpMsgBuf);
    LocalFree(lpDisplayBuf);
    ExitProcess(1);
}

可能有助于发布您在应用程序中调用gcc的代码。我怀疑您需要指定gcc可执行文件的完整路径,因为很可能没有像命令解释器中那样的“搜索路径”。 - lothar
错误是来自您的调用吗?就我了解gcc/g++的工作方式,它们会启动其他进程,可能找不到这些进程。您使用的命令提示符是g++正常工作的Windows命令提示符还是Cygwin的命令提示符? - Alexey Ivanov
@lothar:完成。@Alexey:在cmd中,g++可以正常工作。我使用我的C++代码(现已粘贴)。我运行它并收到错误信息。该错误来自于g++的标准输出流。 - user34537
根据您的代码,错误不是来自gcc,而是来自您的代码:_您的程序_无法启动gcc。您是否尝试在路径中使用反斜杠,例如这样:string gcc_bin="E:\\dev\\external\\MinGW\\bin\\g++.exe"; - Alexey Ivanov
@Alexey:是的,它确实来自gcc。否则,我的函数会返回错误而不是在stdout中找到它。例如,编辑文件夹,我会收到一个窗口消息,而不是从stdout输出。 - user34537
10个回答

6
尝试将g++编译器的路径添加到PATH环境变量中:
TCHAR *path;
TCHAR *newpath;
DWORD dwSize = GetEnvironmentVariable(TEXT("PATH"), NULL, 0);

path = new TCHAR[dwSize];
GetEnvironmentVariable(TEXT("PATH"), path, dwSize);


dwSize += MAX_PATH;
newpath = new TCHAR[dwSize];
_tcscpy_s(newpath, dwSize, TEXT("E:\\dev\\external\\MinGW\\bin;"));
_tcscat_s(newpath, dwSize, path);
SetEnvironmentVariable(TEXT("PATH"), newpath);

delete[] path;
delete[] newpath;

此时,您的进程的环境块包含PATH变量,其中包括g++编译器的路径。注意:这不会影响用户的环境。

您可以使用char代替TCHAR,并使用strcpystrcat。这种方式将在启用Unicode和不启用Unicode支持的情况下都起作用。


4

很有可能系统上存在两个编译器实例。

如果是这样的话,可以尝试以下操作,让当前路径下的编译器用于源代码编译:

D:\cmn_dev\mingw64\bin>.\g++ HelloGcc.cpp -o Hello.exe

希望这能帮到您。祝好。

3
你使用的是哪个适用于Windows的GCC?MinGW,Cygwin还是其他什么?
你是否尝试过按照这个问题中指示的注销并重新登录?CreateProcess: No such file or directory 在Windows上,GCC需要其bin目录位于PATH上,它不会在其自己二进制文件所在的目录中查找。尝试将类似以下内容的东西放置在其中:
wchar_t buf[4096];
ExpandEnvironmentStringsW(L"%PATH%", buf, 4095);
OutputDebugStringW(buf);

在调用 g++ 之前将该目录添加到程序环境的路径中(如果您没有在调试器中运行程序,请改用 wprintf),以确保程序能够访问它。
如果您尝试在路径中使用空格字符安装 GCC,请注意,MinGW 和 Cygwin 都会发出警告。

我尝试过了,但可能做错了。我已经添加了我的代码。当我尝试执行我的createprocess时,在path=gcc_bin;path;\0\0中添加会导致错误87参数不正确 - user34537
“E:/dev/external/MinGW/bin” 在 buf 中显示吗?如果没有,您需要将其添加到系统环境变量中(在 XP 上,请参阅 http://support.microsoft.com/kb/310519,在 Vista/7 上,请使用 Windows 键->“环境”),然后重新登录。 - BCoates
其他人将需要使用这个应用程序,我不想在他们的环境变量中瞎搞。此外,我将其添加到 ExpandEnvironmentStrings 中,就像我的代码所示。只是因为我做错了什么或其他原因导致我调用自己的 createproccess 时出现参数错误。 - user34537
我忘了提到。我已经在我的路径中重新启动了它,但是没有成功。但我没有在CreateProcess中使用ExpandEnvironmentStrings,因为它会给我返回参数87无效的错误。 - user34537
我曾经遇到过同样的问题,这个问题给了一个很好的方向:在cmd.exe中输入> which g++.exe,输出为...\avr8-gnu-toolchain\avr\bin\g++.exe,显然不能编译控制台应用程序。将%path%前置为MinGW/bin目录可以解决这个问题。 - mMontu

2

我曾经遇到过同样的问题,在将"C:\MinGW\msys\1.0\bin"添加到PATH系统变量后,这个问题得到了解决。


1
使用Sysinternals ProcessMonitor(http://technet.microsoft.com/en-us/sysinternals/bb896645)跟踪您的代码发出的系统调用(CreateFile、CreateProcess、Registry查询)以及它们的成功和返回值。这还显示了所有不同的尝试查找可执行文件,这些文件未被您的代码找到 - 大多数情况下,这使得很明显,哪个错误(例如,拼写错误、转义、路径中的空格等)导致代码无法找到g++可执行文件。

1

像BertNase所说,使用Sysinternals ProcessMonitor。您要做的是在进程名称列中查找执行编译的.exe名称,例如gcc.exe。然后查看结果列中任何不是SUCCESS的内容,并检查它们。我认为您要寻找的是NAME NOT FOUND结果。

我遇到了同样的问题,并按照上述方法操作,发现gcc.exe对cc1obj.exe获得了NAME NOT FOUND结果。因此,我进行了猜测,并进入我的MinGW文件夹下的\libexec\gcc\mingw32\4.5.0(版本号可能对您不同),并复制了cc1.exe,然后将其重命名为cc1obj.exe。然后问题就解决了。

您可能没有缺少相同文件,但按照这个过程应该能解决问题。


0
昨天我遇到了一个问题,一个程序无法处理这样的路径:

<some stuff>;%ProgramFiles%\path\to\bins;<some other stuff>

我用以下内容替换了它:

<some stuff>;C:\Program Files\path\to\bins;<some other stuff>

它起作用了。你可能想要检查一下这个。


0
我在设置Atom的时候也遇到了这个问题。但后来我发现我的MinGW是从Codeblocks文件夹中复制过来的。通过使用官方MinGW安装程序重新安装软件包,并在我的情况下将目录路径(例如C:\ MinGW \ bin)添加到高级系统设置>环境变量>路径中,解决了我的问题。

0

你得到的错误提示是gcc函数“CreateProcess”试图访问某个文件,但找不到它。

显然,如果gcc捕获了这个错误,它就在运行中,所以你的PATH没有问题。

然而,gcc找不到编译所需的程序或库。这是我在mingw32上遇到的奇怪错误。我的最佳建议是重新安装mingw32。你可能已经更改了程序使用的某些文件。


0

虽然这是一个旧帖子,但谁知道它可能会有所帮助。

对我来说,我用编译器的位置替换了完整路径。

所以:

set path="< folder that contains the compiler>"

我认为当前路径中可能存在一些编译器无法正确解析的元素(没有双引号,没有空格等)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接