segmentation fault :-(



  • Hallo erst mal alle miteinander 🙂

    Vorweg:
    Ich weiss, es ist ganz schlechter Stil, den kompletten Quellcode zu posten,
    aber leider hab ich keinen blassen Schimmer, wo der Fehler liegen könnte 😮

    Momentan bin ich dazu "verdonnert" C zu lernen.
    Auf dem Stundenplan stand grade die dynamische Speicheranforderung.

    kurze Beschreibung, was das untenstehende Prog machen soll(te):
    eine Beliebige Anzahl von Zeichen von der Kommandozeile einlesen und wieder ausgeben.

    Es tritt folgender Fehler auf:
    unter winXP-Dosbox:
    werden mehr als 1 1/2 Zeilen lang Buchstaben eingetippt, so wird meistens nur noch das letzte Zeichen ausgegeben, mir is es aber auch schon passiert, dass einige wirre Zeichen erschienen sind.

    Linux-Konsole:
    wird mehr als eine ganze Zeile eingegeben, krieg ich einen segmentation fault.

    Es liegt wohl irgendwo an den verfl**** Zeigern 🙂
    Aber wo??

    Anmerkung:
    string.h wurde absichtlich nicht eingebunden (strlen, strcpy usw...)

    #include <stdio.h>
    #include <stdlib.h>
    
    // ermittelt die Länge eines Strings (ohne \0, nur Anzahl der Zeichen)
    int strLen(char * str);
    
    // Kopiert einen String in einen anderen
    int strCpy(char * target, char * source);
    
    // liest eine beliebige Anzahl an Zeichen von der Tastatur ein
    // und gibt einen Zeiger auf diesen String zurück
    char * getStr();
    
    // Beendet das Programm
    void die(int errCode);
    
    /////////////////////////////////////////////////////////////////////
    int main()
    {
    char * string;
    
    	// String einlesen
    	string=getStr();
    
    	// String ausgeben
    	printf("%s\n",string);
    
    return 0;
    }
    
    /////////////////////////////////////////////////////////////////////
    // liest eine beliebige Anzahl an Zeichen von der Tastatur ein     //
    // und gibt einen Zeiger auf diesen String zurück		  //
    /////////////////////////////////////////////////////////////////////
    char * getStr()
    {
    char * aString;
    char * aTemp;
    char sign=0;
    int strLength=0;
    char stat=0;
    
    	while ((sign=getchar()) != '\n')
             {
    
                     // Falls es sich NICHT um den ersten Durchlauf handelt
                     // (stat wird bei jedem Durchlauf um 1 erhöht, beginnend bei 0)
             	if (stat > 0)
                     {
                     // Anzahl der Zeichen in aString ermitteln
                     strLength=strLen(aString);
    
                     // Speicher reservieren und aTemp draufzeigen lassen
                     // (es wird ein Byte mehr angefordert, als Zeichen in aString sind,
                     // dieses wird für die \0 benötigt)
    	        aTemp = (char *) malloc(sizeof(char) * strLength + 1);
                     	if (aTemp == NULL){die(1);}
    
                     // aString nach aTemp kopieren
             	strCpy(aTemp,aString);
    
                     // Speicher an der Stelle aString freigeben
                     free(aString);
    
                     // Speicher reservieren und aString drauf zeigen lassen
                     // Es werden 2 Byte mehr reserviert, als der alte String
                     // Zeichen hatte (1 Byte für das neue Zeichen, 1 Byte für \0)
                     aString = (char *) malloc(sizeof(char) * strLength + 2);
                     	if (aString == NULL){die(2);}
    
                     // aTemp nach aString kopieren
             	strCpy(aString,aTemp);
    
                     // Neues Zeichen anhängen
             	aString[strLength]=sign;
                     // \0 anhängen
             	aString[strLength+1]='\0';
    
                     // speicher von aTemp freigeben
             	free(aTemp);
                     }
                     // else-Zweig wird nur beim ersten Durchlauf ausgeführt
                     else
                     {
                     // 2 Byte reservieren
                     aString = (char *) malloc(sizeof(char)* 2);
                     // Zeichen anhängen
                     aString[0]=sign;
                     // \0 anhängen
                     aString[1]='\0';
                     }
    
             stat++;
             }
    
    return aString;
    }
    
    /////////////////////////////////////////////////////////////////////
    // liefert die Anzahl der Zeichen in einem String                  //
    // (ohne '\0')                                                     //
    /////////////////////////////////////////////////////////////////////
    int strLen(char * str)
    {
    int i=0;
    	while(str[i] != '\0')
             {i++;}
    return i;
    }
    
    /////////////////////////////////////////////////////////////////////
    // Kopiert einen String in einen anderen                       //
    /////////////////////////////////////////////////////////////////////
    int strCpy(char * target, char * source)
    {
    int i=0, sourceSize;
    
             sourceSize=strLen(source+1);
    
             for (i=0; i<sourceSize+1; i++)
             {
             target[i]=source[i];
             }
    
    return sourceSize;
    }
    
    /////////////////////////////////////////////////////////////////////
    // Beendet das Programm                                            //
    /////////////////////////////////////////////////////////////////////
    void die(int errCode)
    {
    printf("\n Es ist Fehler %d aufgetreten\n",errCode);
    exit(errCode);
    }
    

    schon mal danke für eure Hilfe

    cu
    Martin



  • Habs mir erst kurz angeschaut... und vielleicht habe ich auch
    was übersehen..
    ..
    aber frag dich mal, was genau beim ERSTEN Durchlauf in der
    while-Schleife von getStr in aString steht.

    sieh dir besonders folgende drei Zeilen an:
    strLength=strLen(aString);
    strCpy(aTemp,aString);
    free(aString);



  • danke für die schnelle antwort

    hmmm...

    Beim ersten Durchlauf von getStr() steht irgendwas undefiniert willkürliches in aString.
    Drum is ja die Abfrage
    if (stat > 0)
    wobei "stat" mit 0 vorinitialisiert wurde,
    und nach jedem Durchlauf von while um 1 erhöht wird.

    Es sollte eigentlich der else-Zweig ausgeführt werden.

    strLength=strLen(aString); strCpy(aTemp,aString); free(aString);
    sollten also erst ab dem zweiten Durchlauf aufgerufen werden...

    cu

    PS: ich hab jetzt mal die Zeichen gezählt:
    Windows: bis 128 Zeichen geht alles gut, ab dem 129. geht's nimma
    Linux: hier is bei 80 Zeichen schluss...

    PPS: noch ne Frage:
    kann ich auf den Zeiger, der mir von getStr() zurückgeliefert wird,
    free() anwenden?



  • anonymus schrieb:

    Drum is ja die Abfrage
    if (stat > 0)

    Sorry... hab ich übersehen

    anonymus schrieb:

    kann ich auf den Zeiger, der mir von getStr() zurückgeliefert wird,
    free() anwenden?

    auf jeden Fall, ja

    na dann schau dir mal als weiteres "stat" an.. du zählst es immer weiter hoch.. obwohl du die Variabel doch eigentlich sonst gar nicht benötigst... ?
    Deshalb meine nächste Frage: wie weit darfst du stat hochzählen?



  • *Autsch*

    2:1 für dich 🙂

    Mein Contra:
    hab stat++ durch stat = 1 ersetzt
    unter Windows läufts jetz (getestet bis 800 Zeichen :-),
    aber unter Linux krieg ich immer noch ab dem 81. Zeichen einen segmentation fault... ???

    thx
    Martin



  • genau 😉
    stat = 1 kannst du auch gleich in den "else"-Block verschieben...
    und vielleicht solltest du dafür nicht gerade ein "char" verwenden...
    ein "unsigned" wäre da schöner...

    Aber weshalb der Code jetzt noch unter Linux einen Crash verursacht ist mir schleierhaft...
    Ist es auch sicher der gleiche Code?
    Auf welcher Zeile schmiert das Programm ab ? (Debugger)



  • char hab ich verwendet, weil's nur ein Byte braucht (von 512 MB ;-).
    in den else-Zweig schieben, ok überzeugt.

    bin mir 100%-ig sicher, dass ich unter linux den selben code hatte.
    aber da werd ich dann mal nächste woche meinen dozenten löchern, der wird schließlich bezahlt dafür *g*

    nochmal danke
    gute n8


Anmelden zum Antworten