Warum bekomme ich einen Segmentierungsfehler in meinem einfachen C ++ Programm mit libexpect.so?

8

Ich bin mit einem Projekt beschäftigt, bei dem ich einige Prozesse in bash oder ssh automatisieren muss, also entschied ich mich für die Bibliothek libexpect.so. Wenn Sie nicht wissen, was Libexpect ist, bietet es eine expect-Erweiterung, die ich in einem C ++ - Programm verwenden kann, und es ist nur ein Programm, in dem Sie automatisierte Skripts für Dinge wie ssh ausführen können. So kann ich ein Skript ausführen, das irgendwo ssh versucht ... wenn die Passwortaufforderung von mir erwartet wird, hätte ich schon ein Passwort zum Senden erwarten können.

Mein Problem ist, dass ich einen Segmentierungsfehler bekomme, den ich mit gdb auf eine Funktion in libexpect.so beschränkte, die exp_spawnv genannt wird, wenn ich ein Programm benutze, sogar ein wirklich einfaches.

Ich weiß, dass ich die Bibliothek richtig verlinkt habe, es kompiliert und das ganze Problem existiert nicht, wenn ich in ubuntu kompiliere und laufe, aber in meiner arch linux-Installation erhalte ich den Segmentierungsfehler, den ich später ausführe . Der Grund, warum ich es auf Arch baue, ist, weil ich das Projekt schließlich auf den meisten Distributionen erstellbar machen möchte.

Meine Gedanken sind, dass in meiner Arch-Installation Berechtigungen existieren, die beim Aufruf der Funktion exp_spawnv fehlschlagen, vielleicht eine Pipe, Fork oder was auch immer.

Um zu beweisen, dass ich nicht etwas funky mache, hier ist eine einfache main.cpp zu Illustrationszwecken.

%Vor%

Es handelt sich also um das einfachste Programm, das je gemacht wurde. Hier bin ich kompilieren und verknüpfen.

  

$ g ++ -ggdb -c main.cpp

     
    

main.cpp: In der Funktion 'int main ()':

         

main.cpp: 5: 32: Warnung: veraltete Konvertierung von String-Konstante in 'char *' [-Write-Strings]

  
     

$ g ++ main.o -expect -o mainprog

Also habe ich mein ausführbares Mainprog ... nur ausgeführt, das mir einen Segmentierungsfehler und sonst nichts geben wird.

Wenn ich mainprog in gdb ausführe, sagt es mir, dass es in exp_spawnv einen seg-Fehler gibt. Hier ist, was ich in gdb mit dem Backtrace am Ende gemacht habe.

  

(gdb) ausführen

     
    

Startprogramm: / home / user / testlibexpect / mainprog

         

Warnung: Konnte Bibliothekssymbole für linux-vdso.so.1 nicht laden.

         

Benötigen Sie "set solib-search-path" oder "set sysroot"?

         

Programm empfangenes Signal SIGSEGV, Segmentierungsfehler.

         

0x00007ffff7bc8836 in exp_spawnv () von /usr/lib/libexpect.so

  
     

(gdb) zurückverfolgen

     
    

0 0x00007ffff7bc8836 in exp_spawnv () von /usr/lib/libexpect.so

         

1 0x00007ffff7bc8cb4 in exp_spawnl () von /usr/lib/libexpect.so

         

2 0x00007ffff7bc8d01 in exp_popen () von /usr/lib/libexpect.so

         

3 0x000000000040069e in main () bei main.cpp: 5

  

Zwei Dinge betreffen mich.

  1. Wenn ich auf die Manpage für libexpect schaue, weiß ich, dass exp_spawnv einen neuen Prozess gibt und ich über die FILE * kommunizieren kann. Ich nehme also an, dass das SIGSEGV-Signal empfangen wird, weil mit der Gabel etwas Schlimmes passiert ist?

  2. Diese Zeile (Warnung: Konnte Bibliothekssymbole für linux-vdso.so.1 nicht laden.) in der Backtrace sieht fischig aus?

Also zusammenfassend ist meine Frage, was ich untersuchen sollte, um dieses Problem zu beheben? Ich habe versucht, die expect-Bibliothek aus der Quelle zu bauen und sie mit dem arch package manager pacman zu erwerben ... das Problem besteht fort, so dass ich nicht glaube, dass der Build der Bibliothek beschädigt ist, wenn Sie wissen, was ich meine.

EDIT: Punkt 2 meiner Bedenken ist kein Problem, nach meiner Forschung, nur Kosmetik.

Die Demontage von Eclipse ist unten:

%Vor%

DIE ANTWORT, MIT DER ICH HERGESTELLT HABE

Hier ist die Lösung, die mir schließlich einfällt: Ich habe szx 'Antwort akzeptiert, weil sie mich auf diesen Weg geführt hat, der trivial war, sobald ich wusste, wonach ich suchte.

%Vor%

Alles, was ich hier getan habe, wird gezeigt, wie expect / tcl initialisiert wird, um das Problem zu verhindern, über das szx geredet hat. Dann habe ich einfach ein typisches expect like Problem gemacht, bei dem ich ziemlich viel gesagt habe, wenn die Shell dich zur Eingabe auffordert, sende es pwd. Dann, wenn es dir das aktuelle Verzeichnis gibt, funktioniert expect. Diese Art von Struktur kann für etwas wie ssh sehr nützlich sein. Sagen Sie, wenn Sie irgendwo Sshing automatisieren, etwas tun und dann wieder rausgehen wollen. Vor allem, wenn Sie es ein paar hundert Mal tun möchten und Sie nicht die Authentizität jedes Hosts bestätigen und jedes Mal ein Passwort eingeben möchten.

Beachten Sie, dass ich das aus irgendeinem Grund nie auf ubuntu tun musste, weil ich es nicht aus der Quelle erstellt und nur apt-get verwendet habe. Allerdings erfordert mein Projekt, dass ich aus der Quelle baue, also fand ich einen wirklich guten, sauberen Weg, es auf Ссылка und Ссылка ...Tatsächlich scheint die ganze Website wirklich nützlich zu sein.

Nochmals vielen Dank an szx

    
benzeno 04.12.2012, 15:05
quelle

2 Antworten

4

Die in Tcl definierte globale Variable TclStubs *tclStubsPtr ist NULL , wenn exp_spawnv versucht, auf Tcl_ErrnoMsg zuzugreifen, das als Mitglied dieser Struktur definiert ist (siehe tcl.h ):

%Vor%

Ich bin weder mit expect noch mit Tcl vertraut, aber das obige deutet darauf hin, dass Sie wahrscheinlich ein Initialisierungs-Unterprogramm aufrufen sollten (falls eines existiert) oder es manuell einstellen.

    
szx 05.12.2012, 02:50
quelle
1

Am meisten beunruhigt mich die Warnung beim Kompilieren. Die Schnittstelle erfordert, dass Sie eine schreibbare Zeichenfolge übergeben, aber Sie übergeben eine Zeichenfolge-Konstante. Wenn es tatsächlich schreibt, wird dies zu einem Segmentierungsfehler führen. Es sieht also nach einem guten Kandidaten für Ihr Problem aus.

Was passiert, wenn Sie stattdessen versuchen, einen beschreibbaren Puffer zu erstellen und diesen übergeben:

%Vor%

Update: Ich habe Ihr Programm getestet (mit der obigen Änderung und einem "Return 0;" am Ende), und es funktioniert gut für mich. Vielleicht stimmt etwas mit Ihrem System nicht, wie eine halb installierte Bibliothek? Sie können überprüfen, ob es auch fehlschlägt, wenn Sie mit -static verknüpfen. Wenn Sie das tun, sind Sie sicher, dass die mit der Kompilierung verknüpfte Bibliothek mit der Laufzeitbibliothek identisch ist (da sie zur Kompilierungszeit in die ausführbare Datei eingeschlossen wird).

    
Bas Wijnen 04.12.2012 15:16
quelle

Tags und Links