execvp не работает при преобразовании из вектора & lt; string & gt; на вектор & lt; char * & gt; на символ **

Переход от вектора строк к вектору 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;
}

0

Решение

Во-первых, нет смысла копировать std::strings если следующая вещь, которую вы собираетесь сделать, это позвонить execvp,

Если execvp в случае успеха, то он никогда не вернется, и весь образ памяти исчезнет в дым (или, точнее, будет заменен на совершенно новый образ). В процессе построения нового образа, exec* скопирует в него массив argv (и массив environment). В любом случае, std::vector а также std::string деструкторы никогда не будут вызваны.

Если, с другой стороны, execvp терпит неудачу, тогда переданный в него аргумент не будет изменен. (Posix: «The 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*> из 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;
}
3

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector