Problem bei übergabe von char *array[] / execvp aufruf
-
Hallo und danke für deine schnelle Antwort

Klar! Die Variable tmpCString ist nur in der Funktion gültig, das habe ich wohl nicht beachtet.Wie du es vorgeschlagen hast(mit einem Vector), hätte ich meine Funktion eigentlich auch geschrieben, nur ist mir der aufruf von execvp(...) anschließend nicht möglich oder ?
Verstehe ich das richtig:
char *parameters[MAXLINE] ist eine misxhung von c++ und c und sollte so nicht genutzt werden ?
-
DaJon_ schrieb:
Wie du es vorgeschlagen hast(mit einem Vector), hätte ich meine Funktion eigentlich auch geschrieben, nur ist mir der aufruf von execvp(...) anschließend nicht möglich oder ?
Wieso nicht? Aus einen std::string kann man doch leicht einen C-String machen.
Verstehe ich das richtig:
char *parameters[MAXLINE] ist eine misxhung von c++ und c und sollte so nicht genutzt werden ?Nein, diese Zeile selbst ist einfach typisches C. In C++ würde man das nie so machen. Der Rest deines Programms ist aber (teilweise) C++. Daher ist dein Gesamtprogramm eine Mischung aus C und C++. C und C++ arbeiten aber nicht sonderlich gut zusammen.
-
Wieso nicht? Aus einen std::string kann man doch leicht einen C-String machen.
Ja, nur muss ich aus einem Vector ein 2 Dim. C Array machen, wenn ich das richtig verstehe?
-
DaJon_ schrieb:
Wieso nicht? Aus einen std::string kann man doch leicht einen C-String machen.
Ja, nur muss ich aus einem Vector ein 2 Dim. C Array machen, wenn ich das richtig verstehe?
Welche Version von execvp willst du denn einsetzen?
-
Ehrlich gesagt kenne ich nur eine Version:
int execvp(const char *file, char *const argv[]);
-
Dann würde ich vor dem Aufruf einen
vector<const char*>erstellen, diesen mit denc_str()s aus demvector<string>füllen und dann einen Zeiger auf das erste Element (alsodata()) an execvp übergeben.
-
Das klingt gut vielen dank

Nur weiss ich nicht, wie ich einen Zeiger auf das erste Element übergebe und was du mit data() meinst ?
-
DaJon_ schrieb:
Das klingt gut vielen dank

Nur weiss ich nicht, wie ich einen Zeiger auf das erste Element übergebe und was du mit data() meinst ?Na, entweder
&mein_vector[0]oder ebenmein_vector.data().
-
Ah danke

Leider funktioniert mein execvp Aufruf noch nicht:"No matching function for to call 'execvp'"
int status; std::vector<const char *> params; const char* comm = command.c_str(); // Füllen des Vectors, fork() etc. status = execvp(comm,params.data());Habe mir execvp nochmal angeschaut:
int execvp(const char *, char * const *);warum kann ich die Funktion nicht aufrufen ?

-
Hier mal ein Beispiel: http://stackoverflow.com/questions/5846934/how-to-pass-a-vector-to-execvp
Eventuell musst du deinem Compiler mitteilen das er C++11 oder neuer verarbeiten soll.
Ältere C++11 Compiler erfordern bei Strings in einigen Fällen die C-Variante. Mit C++11 werden Strings mehr im C++ Stil unterstützt.
MfG f.-th.
-
Was genau hat das mit älteren oder neueren C++11-Compilern zu tun?
@OP:
Das Problem ist, dass execvp ein char * const * (Zeiger auf konstante Zeiger auf Char) erwartet, Du ihm aber ein char const * (const) * (Zeiger auf Zeiger auf konstante Char) gibst. Der Vector muss ein vector<char*> sein (das zunächst mal unabhängig von der Sprachversion).
Da aber string::c_str einen Zeiger auf const liefert, musst Du hier hässlicherweise das const wegcasten, sonst geht es nicht. Das ist an dieser Stelle aber sauber, da wir "wissen", dass execvp die Strings nicht verändert.
Hint: &command[0], um einen nicht-konstanten Zeiger auf den String zu bekommen, ist nicht ratsam, da der String dann nicht zwingenderweise nullterminiert sein muss.
-
LordJaxom schrieb:
Da aber string::c_str einen Zeiger auf const liefert, musst Du hier hässlicherweise das const wegcasten, sonst geht es nicht. Das ist an dieser Stelle aber sauber, da wir "wissen", dass execvp die Strings nicht verändert.
So hat es geklappt. vielen lieben Dank

-
Nachdem der Aufruf funktioniert hat, habe ich leider ein weiteres Problem.
Der Vector wird scheinbar nicht richtig übergeben..// ... int status; std::string command; std::vector<const char *> params; // command und params wird gefüllt... // Testausgabe for (int i=0; i<params.size(); i++) { std::cout<<"params in Kind an stelle "<<i<" "<<<params[i]<<std::endl; } std::cout<<"Command in Kind : "<<command<<std::endl status= execvp(const_cast<char*>(command.c_str()),const_cast<char**>(params.data())); // hier das Problem ?Nach eingabe von "echo test" erscheint folgende Ausgabe:
"params in Kind an stelle 0 test
Command in Kind : echo
// leerzeile
"Der echo Befehl wird also ausgeführt, sonst wäre keine leerzeile vorhanden, allerdings verschluckt er das erste Argument.
Wenn ich allerdings "echo test1 test2" eingebe erscheint folgende Ausgabe:
"params in Kind an stelle 0test1
params in Kind an stelle 1test2
Command in Kind : echo
test2"Hier wird also der echo Befehl ausgeführt, allerdings nur mit dem 2.Parameter und der Erste wird wieder verschlungen.
Jemand eine Idee woran das liegen könnte ?
LG
-
man execvp schrieb:
The execv(), execvp(), and execvpe() functions provide an array of pointers to null-terminated strings that represent the argument list available to the new program. The first argument, by convention, should point to the filename associated with the file being executed. The array of pointers must be terminated by a NULL pointer.
-
Soo bin wieder ein Stück weiter doch hänge erneut an einem Problem:
//... std::vector<char*> params; while(1){ // Füllen von params etc. // params.push_back(NULL); // Bei Ausführen dieses Befehls erscheint gar keine Ausgabe // Testausgabe for (int i=0; i<params.size(); i++) { std::cout<<"params in Kind an stelle "<<i<" "<<<params[i]<<std::endl; } status= execvp(const_cast<char*>(params[0]),const_cast<char**>(¶ms.front())); //... params.clear(); }// ende while-SchleifeBei eingabe von "echo test1 test2":
"
params in Kind an stelle 0 echo
params in Kind an stelle 1 test1
params in Kind an stelle 2 test2
test1 test2"-Also genauso wie ich es erwartet habe.
Gebe ich anschließend "echo test3" ein erscheint folgende Ausgabe:
"
params in Kind an stelle 0 echo
params in Kind an stelle 1 test3
test3 test2"-Der vector params hat wie erwartet nur 2 Stellen. Trotzdem wird mir der 2. Parameter vom Durchlauf davor mit ausgegeben.
Meine Vermutung:Der compiler(?) weiß also nicht, wo er aufhören soll die Argumente auszulesen, die trotz des params.clear() befehl noch im Speicher vorhanden sind ?Das anfügen von NULL (wie oben auskommentiert) führt allerdings dazu, dass gar keine Ausgabe erscheint, was mich verwundert

Ich hoffe ihr könnt mir weiterhelfen

LG
-
Leider sieht man an Deinem Code nicht, wann Du NULL in den Vector pusht. Jedenfalls sieht man in der Ausgabe nichts davon, dass am Ende des Vectors noch ein Element mit dem Inhalt NULL vorhanden ist.
Tipp für die Korrektur: NULL nach cout zu schreiben ist undefined, Du müsstest also dort etwas wie
std::cout << (params[i] != NULL ? params[i] : "NULL")"machen.
Und benutze nullptr
