问题描述
从字符串向量到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;
}
首先,如果下一步要做的是调用execvp
,则复制std::string
没有任何意义.
如果execvp
成功,则它将永远不会返回,并且整个内存映像将消失在烟雾中(或更准确地说,将其替换为全新的映像).在构造新映像的过程中,exec*
将argv数组(和环境数组)复制到其中.无论如何,将永远不会调用std::vector
和std::string
析构函数.
另一方面,如果execvp
失败,则传递给它的参数将不会被修改. (Posix:指针的argv[]
和envp[]
数组以及这些数组所指向的字符串不得通过调用exec函数之一进行修改,除非由于替换了过程映像而导致.")/p>
在任何一种情况下,都不需要复制字符串.您可以使用std::string::c_str()
提取指向底层C字符串的指针(作为const char*
,但请参见下文).
第二,如果您使用的是C ++ 11或更高版本,则std::vector
随便带有data()
成员函数,该成员函数返回指向基础存储的指针.因此,如果您有std::vector<char*> svec
,则svec.data()
将是基础char*[]
,这就是您要传递到execvp
的内容.
因此问题减少到了从std::vector<std::string>
创建std::vector<char*>
的过程,这很简单:
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;
}
Going from a vector of strings to a vector of char* to a char**, was working when the argument came in as char**, but the conversion seems to have a problem and I'm not able to find the difference.
Is there a better way to do this?
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;
}
First, there's no point in copying the std::string
s if the next thing you are going to do is call execvp
.
If the execvp
succeeds, then it will never return and the entire memory image will vanish into smoke (or, more accurately, be replaced by a completely new image). In the course of constructing the new image, exec*
will copy the argv array (and the environment array) into it. In any event, the std::vector
and std::string
destructors will never be invoked.
If, on the other hand, the execvp
fails, then the argument passed into it will not have been modified. (Posix: "The argv[]
and envp[]
arrays of pointers and the strings to which those arrays point shall not be modified by a call to one of the exec functions, except as a consequence of replacing the process image.")
In either case, there was no need to copy the character strings. You can use std::string::c_str()
to extract a pointer to the underlying C string (as a const char*
, but see below).
Second, if you're using C++11 or more recent, std::vector
conveniently comes with a data()
member function which returns a pointer to the underlying storage. So if you have std::vector<char*> svec
, then svec.data()
will be the underlying char*[]
, which is what you want to pass into execvp
.
So the problem reduces to creating a std::vector<char*>
from a std::vector<std::string>
, which is straightforward:
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;
}
这篇关于从vector< string>转换时,execvp无法正常工作到vector< char *>字符**的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!