从向量 <string> 转换为向量 <char*> 到 char** 时,execvp 不起作用

red*_*dux 0 c++ vector execvp

当参数作为 char** 传入时,从字符串向量到 char* 向量再到 char** 是有效的,但转换似乎有问题,我无法找到差异。

有一个更好的方法吗?

    vector<string> args;

    /* code that correctly parses args from user input */

    pid_t kidpid = fork();
    if (kidpid < 0)
    {
        perror("Internal error: cannot fork.");
        return -1;
    }
    else if (kidpid == 0)
    {
        // I am the child.

        vector<char*>argcs;
        for(int i=1;i<args.size();i++)
        {
            char * temp = new char[args.at(i).length()];
            for(int k=0;k<args.at(i).length();k++)
            {
                temp[k] = args.at(i).at(k);
            }
            argcs.push_back(temp);
        }

        char** argv = new char*[argcs.size() + 1];
        for (int i = 0; i < argcs.size(); i++)
        {
            argv[i] = argcs[i];
        }
        argv[args.size()] = NULL;

        execvp(program, args);

        return -1;
    }
Run Code Online (Sandbox Code Playgroud)

ric*_*ici 5

std::string首先,如果您要做的下一件事是调用,则复制 s 是没有意义的execvp

如果execvp成功,那么它将永远不会返回,整个记忆图像将消失为烟雾(或者,更准确地说,被一个全新的图像取代)。在构建新图像的过程中,exec*会将argv数组(和环境数组)复制到其中。无论如何,std::vectorstd::string析构函数永远不会被调用。

另一方面,如果execvp失败,则传递给它的参数将不会被修改。(Posix:“指针argv[]envp[]数组以及这些数组指向的字符串不得通过调用 exec 函数之一进行修改,除非替换过程映像。”)

无论哪种情况,都不需要复制字符串。您可以使用std::string::c_str()提取指向基础 C 字符串的指针(作为const char*,但请参见下文)。

其次,如果您使用的是 C++11 或更新版本,std::vector可以方便地附带一个data()成员函数,该函数返回指向底层存储的指针。因此,如果您有std::vector<char*> svec,那么svec.data()将是底层char*[],这就是您想要传递的内容execvp

所以问题简化为std::vector<char*>从 a创建 a std::vector<std::string>,这很简单:

else if (kidpid == 0) {
    // I am the child.
    std::vector<char*> argc;
    // const_cast is needed because execvp prototype wants an
    // array of char*, not const char*.
    for (auto const& a : args)
        argc.emplace_back(const_cast<char*>(a.c_str()));
    // NULL terminate
    argc.push_back(nullptr);
    // The first argument to execvp should be the same as the
    // first element in argc, but we'll assume the caller knew
    // what they were doing, and that program is a std::string. 
    execvp(program.c_str(), argc.data());
    // It's not clear to me what is returning here, but
    // if it is main(), you should return a small positive value
    // to indicate an error
    return 1;
}
Run Code Online (Sandbox Code Playgroud)