Problem bei übergabe von char *array[] / execvp aufruf


  • Mod

    Dann würde ich vor dem Aufruf einen vector<const char*> erstellen, diesen mit den c_str() s aus dem vector<string> füllen und dann einen Zeiger auf das erste Element (also data() ) 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 ?


  • Mod

    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 eben mein_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**>(&params.front())); 
    //...
    params.clear();
    }// ende while-Schleife
    

    Bei 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 😉


Anmelden zum Antworten