Вызов программы на C из C ++ и передача аргументов

У меня есть программа на С ++, и в какой-то момент в моей программе мне нужно вызвать программу на c и передать ей некоторые аргументы.

Я работаю в Linux Env.

файл simpsh — это скомпилированный c-файл в том же каталоге.
result_simpsh_command — строка с данными этого типа
—creat —trunc —wronly f1 и так далее.

Когда я проверяю значения, которые я получаю в программе C, это показывает это вместо

void execute_simpsh(string resulting_simpsh_command)
{
pid_t pid = fork();

if(pid == -1)
perror("Fork failed!");
else if(pid ==0)
{
char* args[256];

string simpsh ="./simpsh";
args [0] = (char*) simpsh.c_str();
string temp_option_holder="";

int nextCommand=1;

for(int i=0;i<resulting_simpsh_command.length();i++)
{
if(resulting_simpsh_command[i] !=' ')
{
temp_option_holder += resulting_simpsh_command[i];
}
else
{
cout<<"saving to argument: "<<temp_option_holder<<endl;
args [nextCommand] = (char*) temp_option_holder.c_str();
temp_option_holder="";
nextCommand +=1;
}

}cout<<"command numbers "<<nextCommand<<endl;
args [nextCommand + 1] = NULL;

if(execvp(args[0],args) == -1)
cout<<"Failed to open simpsh, maybe you didnt compile?"<<endl;
exit(1);
}
else
{
//not important for now

}
}

0

Решение

Много args массив будет недействительными указателями из-за вашего (неправильного) использования c_str,
Указатель становится недействительным, как только буфер строки будет перераспределен.
Некоторые из args указатели также могут указывать на одно и то же, даже если они действительны.

Два варианта для исправления этого (от макушки головы):

Динамическое распределение:

args[nextCommand] = strdup(temp_option_holder.c_str());

который требует освобождения позже.

Или, если вы можете жить с ограничением длины аргумента, вы можете использовать другой массив и избежать управления памятью (но тогда вам нужно беспокоиться о переполнениях):

char arg_strings[256][ARGUMENT_LENGTH] = {0};
char* args[256] = {0};

// ...
assert(temp_option_holder.length() < ARGUMENT_LENGTH);
strncpy(arg_strings[nextCommand], temp_option_holder.c_str(), ARGUMENT_LENGTH);
args[nextCommand] = arg_strings[nextCommand];
0

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

С ++ имеет так много приятных вещей за пределами std::cout, Используй их!

Суть этого решения std::replace()пробелы в командной строке с нулевыми байтами, затем указатели на начало каждой (C) строки в командной строке (удобно использовать нулевые байты из replace() как терминаторы), поместив эти указатели в вектор, мы затем перейдем к execve(),

#include <string>
#include <vector>
#include <algorithm>
#include <iostream>

// Usually I would recommend using const std::string &
// to avoid the copy, but we are going to do violence
// on the argument so we really *want* a writeable copy.
void execute_simpsh( string cmd )
{
pid_t pid = fork();

if ( pid == -1 )
{
perror("Fork failed!");
}
else if ( pid == 0 )
{
// This will hold our pointers -- and is not limited
// to a maximum amount other than available RAM
std::vector< char * > args( { "./simpsh" } );

if ( ! cmd.empty() )
{
// Tokenize -- std::string may contain null chars!
std::replace( cmd.begin(), cmd.end(), ' ', '\0' );

// std::string is zero-terminated in memory, but that
// zero char is not considered by .find() so we add one,
// making the loop below easier.
cmd.append( '\0' );

size_t i = 0;

// Gather pointers to each argument. find_first_not_of()
// skips leading (and embedded) ex-spaces.
while ( ( i = cmd.find_first_not_of( '\0', i ) ) != std::string::npos )
{
args.push_back( cmd.data() + i );
// find() skips to the end of the current argument.
i = cmd.find( '\0', i );
}
}

std::cout << "Tokens: " << args.size() << "\n";

// args.data() is std::vector's underlying array
// of the pointers we pushed. How convenient...
for ( auto token : args.data() )
{
std::cout << "  " << token << "\n";
}

// ...as "array of char *" is exactly what we need.
if ( execvp( args[0], args.data() ) == -1 )
{
std::cout << "Failed to open simpsh" << std::endl;
}

std::exit( 1 );
}
else
{
// ...
}
}

Обратите внимание, что это решение будет беспощадно любой пробелы в командной строке, в том числе в кавычках, и делает не обрабатывать переводы строк, вкладки и т. д. — опять же, ваше оригинальное решение также не ведет себя по-другому, поэтому я оставлю расширение возможностей для вас.

0

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