Segmentation Fault bei strcat?

Dieses Thema im Forum "C/C++" wurde erstellt von daboss, 28.11.2008.

  1. #1 daboss, 28.11.2008
    Zuletzt bearbeitet: 28.11.2008
    daboss

    daboss Keine Macht für niemand!

    Dabei seit:
    05.01.2007
    Beiträge:
    1.294
    Zustimmungen:
    0
    Ort:
    sydney.australia.world
    Heyho,

    Ich habe folgendes Progrämmchen versucht, zu schreiben. (Was es machen soll, steht weiter unten ;) ).
    Code:
    /*
     * filewatch.c
     *
     *  Created on: 27.11.2008
     *      Author: alex
     */
    #include <fcntl.h>
    #include <signal.h>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    
    int main(int argc, char* argv[]){
        //Parametercheck:
        if(argc != 5){
            printf("AnzParam: %i\n", argc);
            printf("Aufruf: filewatch -d directory -f file\n");
            return 1;
    
        //Debugausgabe:
        }else{
            int i;
            for(i = 0;i<5;++i){
                printf("arg %i: %s\n", i, argv[i]);
            }
        }
    
        //Falls die richtigen Parameter uebergeben
        //wurden, diese Uebernehmen:
        int iD, iF = 1;
        char *cD = "\0";
        char *cF = "\0";
        if(strcmp("-d", argv[1])){
            printf("Dir an 1\n");
    
            iD = 0;
            cD = (char*) calloc(strlen(argv[2]), sizeof(char));
            if(cD == NULL){
                printf("Kein Platz fuer die Parameteruebergabe!");
                return 1;
            }else{
                cD = argv[2];
            }
        }
        if(strcmp("-d", argv[3])){
            printf("Dir an 3\n");
            printf("argv[3] [%s], argv[4] [%s]\n", argv[3], argv[4]);
    
            iD = 0;
            cD = (char*) calloc(strlen(argv[4]), sizeof(char));
            if(cD == NULL){
                printf("Kein Platz fuer die Parameteruebergabe!");
                return 1;
            }else{
                cD = argv[4];
            }
        }
        if(strcmp("-f", argv[1])){
            printf("File an 1\n");
    
            iF = 0;
            cF = (char*) calloc(strlen(argv[2]), sizeof(char));
            if(cF == NULL){
                printf("Kein Platz fuer die Parameteruebergabe!");
                return 1;
            }else{
                cF = argv[2];
            }
        }
        if(strcmp("-f", argv[3])){
            printf("File an 3\n");
    
            iF = 0;
            cF = (char*) calloc(strlen(argv[2]), sizeof(char));
            if(cF == NULL){
                printf("Kein Platz fuer die Parameteruebergabe!");
                return 1;
            }else{
                cF = argv[4];
            }
        }
        //Falsche Parameter -> Abbruch:
        if(iF == 1 || iD == 1){
            printf("Aufruf: filewatch -d directory -f file\n");
            return 1;
        }
    
        printf("Dir %s\n", cD);
        printf("File %s\n", cF);
    
        //Pfad zur Datei basteln:
        char *caPfad = strcat(cF, "/");
        caPfad = strcat(cF, cD);
        printf("Pfad: %s\n", caPfad);
    
        //Datei oeffnen und entsprechend reagieren:
        int iFDesc = (-1);
        while(iFDesc == (-1)){
    
            //Crtl-C abfangen
            if(sigaction(SIGINT, NULL, NULL)){
                printf("Vom Benutzer abgebrochen.\n");
                return 0;
            }
            //kill abfangen
            if(sigaction(SIGKILL, NULL, NULL)){
                printf("Via kill beendet.\n");
                return 0;
            }
            int iFDesc = open(caPfad, O_RDONLY);
            if(iFDesc == -1){
                printf("Datei nicht vorhanden!\n");
                sleep(60);
            }else{
                printf("Datei vorhanden!\n");
                unlink(caPfad);
                printf("Datei geloescht.\nInhalt des Verzeichnisses:\n");
    
                char *caBefehl = (char*) calloc(strlen(cD) + 10, sizeof(char));
                if(caBefehl == NULL){
                    printf("Kein Platz fuer den Befehl...\n");
                    return 1;
                }
                caBefehl = strcat("/bin/ls", cD);
                printf("Befehl: %s\n", caBefehl);
        //        execl(caBefehl, "", NULL);
    
                return 0;
            }
        }
    
        return 1;
    }
    
    Damit habe ich aber (mind.) 2 Probleme:

    Zum einen funktioniert die Parameterübergabe offensichtlich nicht so, wie ich mir das Vorstelle. Die Stelle
    Code:
    if([B]strcmp("[U]-d[/U]", argv[3][/B])){
            printf("Dir an 3\n");
            printf("argv[3] [%s], argv[4] [%s]\n", argv[3], argv[4]);
    
            iD = 0;
            cD = (char*) calloc(strlen(argv[4]), sizeof(char));
            if(cD == NULL){
                printf("Kein Platz fuer die Parameteruebergabe!");
                return 1;
            }else{
                cD = argv[4];
            }
        }
    
    führt zu
    .

    Ausserdem bekomme ich an der Stelle
    Code:
    caBefehl = strcat("/bin/ls", cD);
    einen
    Kann mir da bitte jemand weiterhelfen? :)

    Die Aufgabe dazu:
    Als Übung zur Vorlesung Unix/Linux Netzwerkprogrammierung sollen wir ein C-Programm implementieren, das ein, beim Start übergebenes, Verzeichnis alle 60 Sekunden auf die Existenz einer, beim Start übergebenen, Datei überwacht. Existiert die Datei, soll sie gelöscht, der Inhalt des obigen Verzeichnisses mit Hilfe von "ls" ausgegeben und das Programm beendet werden. Ausserdem soll sich das Ding bei Sstrg+C und kill geordnet beenden... :rtfm:
     
  2. Anzeige

    Schau dir mal diese Kategorie an. Dort findest du bestimmt etwas.
    Registrieren bzw. einloggen, um diese und auch andere Anzeigen zu deaktivieren
  3. rikola

    rikola Foren Gott

    Dabei seit:
    23.08.2005
    Beiträge:
    2.133
    Zustimmungen:
    0
    Zum ersten Problem:

    ein 'if (aussage)' wird ausgefuehrt, wenn aussage != 0. strcmp gibt 0 zurueck, wenn die beiden string gleich sind, und einen Wert ungleich 0, wenn sie - wie bei Deinem Beispiel - ungleich sind. Also steht in dem 'if(...)' etwas, was korrekterweise von C als wahr interpretiert wird und somit wird der folgende Block ausgefuehrt.

    Zum zweiten Problem:
    In dem 'if(strcmp("-d", argv[1]))...' Block steht an einer Stelle 'cD = argv[2]'. Hier kopierst Du nichts, sondern laesst cD auf die Adresse von argv[2] zeigen. Diese Variable hat die Laenge 5 ("/opt"), waehrend das "/bin/ls" laenger ist, Du schreibst also mit strcat in einen Speicherbereich, der Dir nicht unbedingt zugaenglich ist.

    Also Vorsicht mit 'char* c = some_string' Zuweisungen, denke genau darueber nach, ob es das ist, was Du willst!
     
  4. #3 floyd62, 28.11.2008
    floyd62

    floyd62 Routinier

    Dabei seit:
    01.05.2007
    Beiträge:
    309
    Zustimmungen:
    0
    Ohne dein Programm genauer durchgecheckt zu haben ...

    Das erste Problem hat rikola ja schon geklärt.

    Als Ergänzung zum zweiten: strcat legt nicht einen neuen Speicherbereich an und kopiert dann seine Argumente rein, sondern hängt einfach das zweite Argument an das erste an und gibt dann im Erfolgsfall einen Zeiger darauf zurück, sonst einen NULL-Pointer. Spätestens wenn du den dann mit "printf" auszugeben versuchst, bekommst du den SEGFAULT (wenn er nicht schon bei dem Versuch auftritt, an den String "/bin/ls" noch was dranzuhängen.)

    Ich glaube, du solltest die ganze Sache mit den Pointern nochmal etwas durchdenken. Wenn du bspw. hier

    Code:
            cD = (char*) calloc(strlen(argv[4]), sizeof(char));
            if(cD == NULL){
                printf("Kein Platz fuer die Parameteruebergabe!");
                return 1;
            }else{
                cD = argv[4];
            }
    
    mit calloc() zunächst Speicher reservierst, der zwar für argv[4] gross genug ist, das abschliessende 0-Byte aber nicht mehr aufnehmen kann (!), und dann den Pointer cD auf argv[4] umbiegst, dann kopierst du nicht Daten von argv[4] nach cD, sondern du programmierst ein klassisches memory leak ...

    Und ganz allgemein kannst du dir die Verarbeitung von Argumenten, die du auf der Kommandozeile übergibst, mit getopts() deutlich vereinfachen. Check einfach mal die Manual-Page ab, da gibts auch Beispiele ...

    Hoffe, das hlft ein bisschen weiter; Gruss
     
  5. #4 daboss, 28.11.2008
    Zuletzt bearbeitet: 28.11.2008
    daboss

    daboss Keine Macht für niemand!

    Dabei seit:
    05.01.2007
    Beiträge:
    1.294
    Zustimmungen:
    0
    Ort:
    sydney.australia.world
    Ah ok, danke. Des mit 0 und !=0 hab ich mich wohl mal wieder vertan. Dachte, ich kann "== 0" abkürzen, aber war wohl nix.

    Die Zuweisungen bei den Srings hab ich mal durch strcpy erstetzt (sollte lt. "C Kompakt und komplett" eher das machen, was ich wollte :) ) und das strcat mit "/bin/ls" hab ich wohl auch bissl falsch angewendet.

    Oh, grad noch floyd's Beitrag gelesen: Stimmt, strlen zählt die 0 garnicht mit^^ Hätt ich in obigem Buch einen Satz weitergelesen..... naja :).

    Danke euch auf jeden Fall, jetzt funktioniert's, so wie's ausschaut :)

    Werd noch bissl zu sigaction scrooglen, zweifel noch bissl dran, das da die Signalbehandlung "richtig" angewendet ist....
     
  6. rikola

    rikola Foren Gott

    Dabei seit:
    23.08.2005
    Beiträge:
    2.133
    Zustimmungen:
    0
    Wenn Du damit meinst, dass Du
    Code:
    if (strcmp ("-d", argv[2]) == 0)
    
    schreiben wolltest, so hast Du Dich damit keineswegs vertan. Das waere der weitaus elegantere und sauberere Weg, da er leichter zu lesen ist. Das sollte auch funktionieren.
     
Thema:

Segmentation Fault bei strcat?

Die Seite wird geladen...

Segmentation Fault bei strcat? - Ähnliche Themen

  1. Segmentation fault -- warum?

    Segmentation fault -- warum?: Hallo, liebe Forengemeinde. Ich habe mal versuch mit meinen spärlichen Programmierünsten in C++ ein programm zu schreiben, welches den...
  2. pacman verabschiedet sich mit 'segmentation fault'

    pacman verabschiedet sich mit 'segmentation fault': Tag auch. Ich suche jetzt seit 2 Tagen nach einer Lösung für mein Problem und dachte ein paar mal, sie gefunden zu haben - letztendlich steh ich...
  3. Segmentation Fault unter Firefox und Seamonkey

    Segmentation Fault unter Firefox und Seamonkey: Sobald ich yahoo.de öffnen möchte kracht mein Seamonkey und Firefox. Terminal Ausgabe: ---------- s.wiederspahn@ws5-43-fra:~> seamonkey...
  4. Segmentation fault at /usr/share/YaST2/clients/sw_single.ycp:162 Segmentation f

    Segmentation fault at /usr/share/YaST2/clients/sw_single.ycp:162 Segmentation f: Moin Moin, ich hab hier auf SLES 9 ein Problem mit yast. Starte ich ihn aus der Konsole (kein X vorhanden, und das soll / muss auch so bleiben)...
  5. preg_match() liefert httpd_error: child pid 4736 exit signal Segmentation fault (11)

    preg_match() liefert httpd_error: child pid 4736 exit signal Segmentation fault (11): Hallo, ich habe einen kleinen Parser in PHP5.2.1 unter Apache 2.2.4 geschrieben, der folgendes Muster in einer LaTeX Datei sucht: $line =...