Aufgabe 3:Anfänger


Zu den ersten beiden Fragen:

  1. Schlägt [m]execvp()[/m] (oder was immer ihr verwendet) fehl, muss der Kindprozess von Hand beendet werden.
  2. Mit [m]==[/m] vergleicht man die Adresszeiger, mit [m]strcmp()[/m] den Inhalt der Zeichenketten.

  1. Du musst nur Speicher freigeben den du dir irgendwann mal mit malloc geholt hast. Der free Aufruf muss exakt den Pointer bekommen den der zugehoerige malloc/calloc/realloc zurueckgeliefert hat. Da ich Deinen Code nicht kenne, kann ich Dir nicht sagen ob ein free ueberhaupt erforderlich ist. Dann ist es beim argv aber generell so, dass es in der mini_sh Zeiger auf Teilstrings eines Puffers mit der kompletten Kommandozeile enthaelt. Du darfst nicht jeden dieser Zeiger freigeben, sondern nur mit einem free den gesamten Puffer. Ausserdem darfst Du den Speicher natuerlich nur im Vater freigeben, denn im Kind wird er ja fuer den exec noch benoetigt! Eine genauere Antwort kann ich Dir mit diesem Schuss ins Blaue leider nicht liefern.

  2. Der Unterschied zwischen den beiden ist, dass calloc den Speicher mit 0 vorinitialisiert waehrend malloc ihn Dir unveraendert (also in undefiniertem Zustand) gibt. Zu Deiner Frage kann ich Dir ohne Code auch hier nichts genaueres sagen, meine Vermutung ist aber, dass der strcpy das Ende des Strings nicht findet und darueber hinauslaeuft. Ansonsten kann der Problem natuerlich auch erst spaeter Auftreten, wobei strcpy aber eigentlich das abschliessende Zeichen mit kopiert…


vielleicht versucht ihr die Adresse free’en, die strtok produziert? Strtok verwendet einen statischen Buffer, soviel ich weiss


char *tmp;
fgets(tmp, 1024, stdin);
printf("Länge von tmp: %i", strlen(tmp));
...

Eingabe: arg1 arg2 arg3

Ausgabe: Länge von tmp: 3


Mit weiteren tests kommt raus, dass fgets nur bis zum 1. Space ließt und dann aufhört…und warum dass denn bitte???

P.S. fgets() ließt allerdings nicht nochmal ein…also er ließt alles was da ist aber auch irgendwie doch nicht… :frowning:


ich glaub nicht, dass fgets fuer dich automatisch Speicher allokiert, also mach’s selber


ähm du weißt char *tmp doch nen speicherbereich zu oder???


hab noch 1024 Bytes speicher per malloc zugewiesen…sorry hatte ich vergessen…


Genau da wird kein Speicher allokiert. Tja da fragt man sich, warum es denn nicht einen Segfault gibt, bzw. was da passiert.

char *tmp;

Hier wird ein Pointer deklariert, allerdings nicht initialisiert. D.h. das Betriebssytstem reserviert eine Stelle im Speicher - nicht mehr und nicht weniger. An der Stelle (an deren Ende ja irgendwo physikalisches RAM liegt) steht vorher irgendwas drinnen.

fgets(tmp, 1024, stdin);

Nun sagst du dem fgets, es solle doch bitte von stdin Zeichen einlesen und an die Adresse schreiben, auf die tmp zeigt.
Nun gibts im Prinzip 2 Moeglichkeiten:

  1. Die Adresse liegt nicht in einem Segment, fuer das dieser Prozess schreibrechte hat. Dann gibts einen Segfault.
  2. Zufaellig liegt die Adresse in einem Segment, das beschrieben werden kann. z.B. ein Bereich, der mal gemalloct wurde. Dann wird dort reingeschrieben. Das Programm laeuft erstmal weiter - nur irgendwann zeigt sich merkwuerdiges Verhalten, schlieslich wurde ja Speicher in dem sinnvolle Sachen standen ueberschrieben. Derartige Fehler sind schwer zu finden, da sie immer wieder an anderer Stelle auftreten koennen.

Nun die Frage, wie man sowas verhindern kann. Erstens natuerlich durch sauberes Programmieren, sich immer klar machen, was tut eine Funktion eigentlich. Dann helfen einem tools wie valgrind, das in dem Fall irgendwas von ‚use of uninitialised variables‘ und dann ‚invalid write‘ ausspucken sollte. Ein weiterer Tipp ist mit -lefence als zusaetzlichen Parameter zu kompilieren. Das hat den Effekt, dass um allokierte Bereiche der electric fence steht und euch sofort einen segfault schmeisst, wenn ihr zu weit schreibt.


oh, das ist aber gut zu wissen!


Ich hab ein recht komisches Problem.

Unter meinem cygwin daheim läuft das Programm Fehlerfrei, aber wenn ichs dann in der uni über den putty starte habe ich den Fehler, dass ich auf den mit fgets gelesenen string später nicht mehr zugreifen kann, außer ich habe vorher ein printf von dem string gemacht :wand:
Ach ja das tritt erst beim zweiten Programmdurchlauf auf. Beim ersten mal funktionierts einwandfrei.

Was kann das denn bitte sein???


Klingt ja sehr mysteriös, aber wahrscheinlich ist es wieder mal einer der bekannten Standardfehler. Ich tippe mal darauf, dass du irgendwo die Zeiger durcheinander wirfst oder auf Speicher zugreifen willst, den du vorher schon wieder freigegeben hast. Mit [m]gdb[/m], [m]valgrind[/m] oder [m]efence[/m] solltest du die Ursache recht schnell eingrenzen können.


Hi,
mein Programm lässt sich super kompilieren, aber beim Laufen bringts mir einen Segmantation fault, nachdem ich den Befehl eingegeben habe.
Beim Debuggen kommt raus, dass der Fehler in strncpy() ist.
Da wollte ich mal fragen, was könnte da falsch gelaufen sein? Der Befehl ls ist auf alle Fälle nicht zu lang.


bist du sicher, dass alle pointer die die strncopy() uebergibst auch richtig initialisiert sind?


Ich denke schon, der erste ist ein globaler statischer char *, der zweite ein lokaler char *, und die Länge ist bei mir 128.
EDIT: und alle sind ge-malloced und in den zweiten hab ich davor die Eingabe eingelesen


Schau doch mal an, ob der pointer, den malloc ausspuckt und den der strncpy kriegt dieselben sind.

Abgesehen von deinem Fehler klingt “globaler statischer char *” nicht gut. Den besser lokal in eine Funktion packen und evtl. als zusaetzlichen Parameter uebergeben.


Hab grad noch was geändert, hab nur jetzt das Problem, wenn ich das Programm laufen lassen will kommt die Fehlermeldung
mini_sh: permission denied
Kann also net auprobieren, ob des Programm jetzt laufen würde :frowning:


Da hast du vermutlich an den Datierechten rumgefummelt.
Ein “chmod +rx mini_sh” sollte das wieder ausfuehrbar machen.


Dafür bringt er jetzt die Fehlermeldung
mini_sh: Exec format error. Binary file not executable.

Naja, ist wahrscheinlich sowieso zu spät :-/


Dann stimmt wohl mit dem Compiler aufruf was nicht.