2009-05-17 10 views
2

Ich versuche, eine grundlegende bash mit der Verwendung von Systemaufrufen zu tun, aber ich habe ein paar kleine Probleme mit einem Zeiger-Array.Wie lösche ich diesen Array-Zeiger in C?

Um meinen Code fortzusetzen, lese ich Befehle von der stdin mit read() in einen Puffer, dann verwende ich strsep(), um den Befehl von den Argumenten und alle Argumente in ein Array zu trennen. Dann erstelle ich einen neuen Prozess mit fork() und führe diesen Befehl mit den zugehörigen Argumenten mit execvp() aus.

All dies geht in eine Endlosschleife, bis der Benutzer "quit" (noch nicht codiert) eingibt. Das Problem ist, dass ich nach der ersten Iteration * pArgs für den nächsten Befehl und die nächsten Argumente leer haben muss. Und ich weiß nicht, wie es zu tun ...

Hier ist mein Code:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 

int main(int argc, char **argv) { 
    char bBuffer[BUFSIZ], *pArgs[10], *aPtr = NULL, *sPtr; 
    int aCount; 
    pid_t pid; 

    while(1) { 
     write(1, "\e[1;31mmyBash \e[1;32m# \e[0m", 27); 
     read(0, bBuffer, BUFSIZ); 

     sPtr = bBuffer; 
     aCount = 0; 

     do { 
      aPtr = strsep(&sPtr, " "); 
      pArgs[aCount++] = aPtr; 
     } while(aPtr); 

     pArgs[aCount-2][strlen(pArgs[aCount-2])-1] = '\0'; 

     // Debug code to output pArgs content 
     write(1, "|>", 2); 
     write(1, pArgs[0], strlen(pArgs[0])); 
     write(1, "<|", 2); 

     if(strlen(pArgs[0]) > 1) { 
      pid = fork(); 

      if(pid == -1) { 
       perror("fork"); 
       exit(1); 
      } 

      if(pid == 0) { 
       execvp(pArgs[0], pArgs); 
       exit(0); 
      } 
     } 
    } 

    return 0; 
} 

P. S: Sorry, aber ich kann einen Eingang und Ausgang Testfall zur Zeit nicht zur Verfügung stellen. Hoffentlich ist das nicht so schwer zu verstehen und zu beheben, dass ihr es nicht braucht. Ich werde es schreiben später, wenn es aber gebraucht wird ...

einfach löschen Dinge:
Ich weiß, ich fragte, wie das Array zu löschen und ich bekam eine Antwort. Aber es scheint mir jetzt klar zu sein, dass mein Problem nicht das war, sondern der Müll, den der Puffer sammelte, wie Litb herausfand. Es ist sinnvoller, die Zeichenfolge mit dem Nullzeichen zu beenden, als das Array zu löschen. Deshalb markiere ich Litbs Antwort als richtig.

Antwort

2

Ihr Problem besteht darin, dass Sie nach dem Lesen der Daten kein Nullzeichen hinzufügen. So wissen die strsep Anrufe nicht, wo man aufhört. In C müssen Zeichenfolgen durch ein Nullzeichen (das als abschließendes Nullzeichen bezeichnet wird) beendet werden.

// don't forget to add error handling at some point (s == -1) 
ssize_t s = read(0, bBuffer, BUFSIZ-1); 
bBuffer[s] = '\0'; 

Mit dem im Ort, ich sehe nicht, was Array sollte nun geklärt werden, da execvp Argumente bis zum ersten Null-Zeiger gelesen wird. Die do-Schleife fügt jedoch diesen Nullzeiger bereits hinzu, der der Nullzeiger ist, der vom letzten Aufruf von strsep zurückgegeben wurde.

Das Problem würde natürlich auch gelöst werden, indem nur bBuffer gelöscht wird (die Daten, auf die *pArgs zeigt, nachdem der erste Befehl gescannt wurde). Beachten Sie, dass Sie dies auch vor dem ersten Scan durchführen müssen, da Sie nicht davon ausgehen können, dass die Zeichen im Array bBuffer auf einen sinnvollen Wert initialisiert werden.

memset(bBuffer, 0, sizeof bBuffer); 

Platz, die kurz vor dem read Aufruf (aber in jedem Fall BUFSIZE-1 nur maximal lesen, weil das abschließende Nullzeichen Raum müssen!).

Aber wie ich oben gezeigt habe, brauchen Sie diesen Memset-Aufruf nicht. Fügen Sie einfach das abschließende Nullzeichen manuell hinzu.

+0

Ich verstehe nicht, warum meine Antwort downvoted. Offensichtlich wird sein Problem nicht durch nicht Clearing erzeugt das Zeiger-Array, aber das Problem ist woanders. Also einfach zeigen, die richtige Art und Weise zu löschen, dass Array ist gut, aber sicherlich zeigt, wie der Fehler zu korrigieren ist mindestens genauso wichtig! –

+0

Ich denke, seine "Endlosschleife" ist beabsichtigt , und Sie haben die Frage falsch gelesen, aber ich erhebe dies, weil es wichtige Informationen sind, die der Unterzeichner beachten sollte – rlbond

+0

Ich hatte natürlich nicht die Absicht, die Endlosschleife zu durchbrechen, lesen Sie mal, nehmen wir an, BUFSIZ ist 255. Und Sie tippen "echo hallo". die bu ffer enthält dann [echo helloblahblusomerandomdata .......]. Wie soll Strep jemals vernünftig operieren? Und nur das Löschen des Zeiger-Arrays wird es nicht tun. Was er wirklich wollte, ist das bBuffer Array zu löschen. Aber das ist nicht notwendig, wie ich in der Antwort –

7
int i; 
for (i = 0; i < 10; i++) 
    pArgs[i] = NULL; 
+0

Viel besser als ein memset()! –

+2

Ich antwortete mit memset() und löschte dann meine Antwort, weil es zu schwer zu erklären ist, warum sizeof (pArgs) in diesem Fall OK ist, aber in einem anderen Fall möglicherweise nicht OK ist (zB wenn der Typ von pArgs char ** ist) . +1 für die 'for' Schleife, -1 für memset in diesem Kontext. – RichieHindle

+0

Sie sollten es verlassen haben. Memset ist immer noch richtig und ist der bessere Weg zu gehen, wenn Geschwindigkeit ein Problem ist. (Siehe: http://www.cppreference.com/wiki/c/string/memset) Ein vernünftiger Compiler wird dies wahrscheinlich für eine Schleife zu einem Memset optimieren, trotzdem tho – rpetrich

Verwandte Themen