Fault access; read of address nach Ende des Programmes

Schnelle objektorientierte, kompilierende Programmiersprache.
Antworten
nufan
Wiki-Moderator
Beiträge: 2558
Registriert: Sa Jul 05, 2008 3:21 pm

Fault access; read of address nach Ende des Programmes

Beitrag von nufan » Mi Nov 05, 2008 10:44 pm

Da ich in kürze Programmier-Test habe, wollte ich noch ein bisschen üben. ;)
Das Programm soll prüfen, ob ein String ein Palindrom (rückwärts gelesen gleich vorwärts) ist. Funktioniert auch tadellos. Es wird auch ausgegeben, ob es sich um ein Palindrom handelt oder nicht. Nur danach crasht irgendwas. Jedenfalls bekomm ich eine Fehlermeldung mit "Fault access xxx; read of address xxx". Und das nach dem eigentlichen Programmablauf, wo eigentlich gar nix mehr passiert. Hier das main-Programm mit der Stelle wo irgendwas nicht passt:

Code: Alles auswählen

int main ()
{

  char *string, *reversed;                      // string wird eingegeben, und reversed ist string rückwärts gelesen
  int n, pal;                                          // n ist die Anzahl der Buchstaben und pal gibt an, ob es sich 
                                                          // um ein Palindrom handelt (wird von Funktion zurückgeliefert)

  printf ("Number of characters: ");
  scanf ("%d", &n);


  if (n > 0)
  {

    string = (char *) calloc (n, sizeof (char));                    // Speicher für string wird allokiert

    readstring (string, &n);                                             // string wird eingegeben

    reverse (string, reversed);                                        // string wird rückwärts auf reversed kopiert

    pal = compare (string, reversed);                              // string und reversed werden verglichen

    if (pal)                                                                     // hier wird geprüft, ob der String ein Palindrom ist
      printf ("\n\nPalindrom.");

      else
        printf ("\n\nNot a palindrom.");

    free (string);                                                           // Speicher wird wieder freigegeben

  }


  getchar ();

  // Genau hier stürzt das Programm ab

  return 0;

}
Komisch... was kann da nicht stimmen??? Das getchar () wird noch ausgeführt und gleich danach bekomme ich die genannte Fehlermeldung. Spinnt jetzt mein Borland-Compiler oder was? Würde irgendwo ein Zeiger nicht stimmen, würde es bestimmt schon vorher stoppen. Und den allokierten Speicher hab ich danach auch wieder freigegeben (obwohls daran sowieso nicht liegen kann). Ich bin ratlos... :?


EDIT: Sorry für die verwackelten Kommentare, bei mir im Browser-Editor sind sie alle auf der gleichen Höhe.

Benutzeravatar
Dirty Oerti
Beiträge: 2229
Registriert: Di Jul 08, 2008 5:05 pm
Wohnort: Thurndorf / Würzburg

Re: Fault access; read of address nach Ende des Programmes

Beitrag von Dirty Oerti » Do Nov 06, 2008 11:40 am

Puh....
schwer zu sagen.

Von der Meldung her hört es sich schonmal so an, als ob du irgendworauf zugegriffen hast, worauf du nicht zugreifen darfst.
Ich kann nur blind vermuten:

Code: Alles auswählen

string = (char *) calloc (n, sizeof (char));
Das hier der Fehlder liegt und sich dann erst später ausspielt.
Du könntest versuchen mal n+1 Teile zu allokieren.

Warum genau du calloc verwendest verstehe ich auch nicht.
Ändert sich was, wenn du malloc nimmst?

Code: Alles auswählen

string = (char*) malloc(sizeof(char)*(n+1));
Ich hoffe wir kommen so wenigstens in die ungefähre Richtung, in der der Fehler liegt...^^
Bei Fragen einfach an daniel[ät]proggen[Punkt]org
Ich helfe gerne! :)
----------
Wenn du ein Licht am Ende des Tunnels siehst, freu dich nicht zu früh! Es könnte ein Zug sein, der auf dich zukommt!
----
It said: "Install Win95 or better ..." So I installed Linux.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Fault access; read of address nach Ende des Programmes

Beitrag von Xin » Do Nov 06, 2008 2:24 pm

Ich nehme an, dass Du 7 eingibst, wenn Du "Rentner" eingeben möchtest.
Dann speicherst Du in den 7 Buchstaben "Renter"+Nullbyte = 8 Zeichen und zerschießt Dir damit den Stack.
Wenn Das programm endet, also die main-Funktion verlässt stürzt es ab.

SCANF IST GEFÄHRLICH!

Bitte nimm Parameter:
meinprogramm.exe rentner

Code: Alles auswählen

int main( int argc, char ** argv )
{
  printf( "1. Parameter: %s\n", argv[1] );
  return 0;
}
Das Programm gibt "rentner" aus, und zwar vollkommen ungefährlich.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

nufan
Wiki-Moderator
Beiträge: 2558
Registriert: Sa Jul 05, 2008 3:21 pm

Re: Fault access; read of address nach Ende des Programmes

Beitrag von nufan » Do Nov 06, 2008 5:35 pm

Hi!
DirtyOerti hat geschrieben:Du könntest versuchen mal n+1 Teile zu allokieren.
Gleiches Ergebnis wie nur mit "n".
DirtyOerti hat geschrieben:Warum genau du calloc verwendest verstehe ich auch nicht.
Ändert sich was, wenn du malloc nimmst?
Kurz: Nein. Ist genau das selbe.
Xin hat geschrieben:Ich nehme an, dass Du 7 eingibst, wenn Du "Rentner" eingeben möchtest.
Nicht direkt. Am Anfang lese ich einen ungefähren Wert ein. Ich kann auch tausend eingeben und es ändert sich nichts. Und am Ende des Strings setze ich auch \0.
Xin hat geschrieben:SCANF IST GEFÄHRLICH!
Ich weiß. Im ganzen Programm verwende ich nur einmal scanf () und zwar hier:

Code: Alles auswählen

printf ("Number of characters: ");
scanf ("%d", &n);
Hat also nicht direkt mit dem String zu tun. Aber wenn ich den String nicht eingebe sondern zweise, dann funktioniert das auch. Also entweder liegt der Fehler bei der Speicherallokierung oder bei der Eingabe.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Fault access; read of address nach Ende des Programmes

Beitrag von Xin » Do Nov 06, 2008 5:51 pm

dani93 hat geschrieben:
DirtyOerti hat geschrieben:Warum genau du calloc verwendest verstehe ich auch nicht.
Ändert sich was, wenn du malloc nimmst?
Kurz: Nein. Ist genau das selbe.
calloc ist okay.
dani93 hat geschrieben:
Xin hat geschrieben:Ich nehme an, dass Du 7 eingibst, wenn Du "Rentner" eingeben möchtest.
Nicht direkt. Am Anfang lese ich einen ungefähren Wert ein. Ich kann auch tausend eingeben und es ändert sich nichts. Und am Ende des Strings setze ich auch \0.
Wie soll das mit reversed funktionieren? reversed zeigt immer ins Nirvana.
reverse kann an der Tatsache nichts ändern, also muss compare schonmal Mist bauen, in jedem Fall kann es keine Antwort liefern.

Da reverse nie initialisiert wurde, kann es sein, dass durch den Programmaufbau noch auf eine Stelle im Stack zeigt, die Du mit reverse überschreibst und Dir so den Stack zerschießt?
dani93 hat geschrieben:
Xin hat geschrieben:SCANF IST GEFÄHRLICH!
Ich weiß. Im ganzen Programm verwende ich nur einmal scanf ()
Stimmt. Ändert aber nichts an der Tatsache, dass SCANF GEFÄHRLICH IST.
Dass SCANF GEFÄHRLICH IST, kann man eigentlich nicht deutlich genug betonen.
dani93 hat geschrieben:Hat also nicht direkt mit dem String zu tun.
Ich kann den Code nicht kompilieren, aber ich würde wetten, dass Du beim Zugriff auf reverse ins Nirvana schreibst.
dani93 hat geschrieben:Aber wenn ich den String nicht eingebe sondern zweise, dann funktioniert das auch. Also entweder liegt der Fehler bei der Speicherallokierung oder bei der Eingabe.
zweise? Zwei Strings? Kann ich nix mit anfangen, sehe dafür keinen Quelltext.

Wenn Du es nicht rausbekommst, schick mir mal das ganze Ding.

P.S.: SCANF IST GEFÄHRLICH.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

nufan
Wiki-Moderator
Beiträge: 2558
Registriert: Sa Jul 05, 2008 3:21 pm

Re: Fault access; read of address nach Ende des Programmes

Beitrag von nufan » Do Nov 06, 2008 6:05 pm

Xin hat geschrieben:Dass SCANF GEFÄHRLICH IST, kann man eigentlich nicht deutlich genug betonen.
Hängt deine Shift-Taste zeitweise? :)
Ok, habs verstanden.
Xin hat geschrieben:zweise? Zwei Strings? Kann ich nix mit anfangen, sehe dafür keinen Quelltext.
Das sollte "zuweise" heißen :)
Also ich schreib am Anfang des Programms:

Code: Alles auswählen

char string[] = {"rentner"};
Xin hat geschrieben:Wenn Du es nicht rausbekommst, schick mir mal das ganze Ding.
Ok. Die Teile, die ich zurzeit nicht verwende (Eingabe und Speicherallokierung) sind auskommentiert:

Code: Alles auswählen

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
//#include <conio.h>

void reverse (char *string, char *reversed);
int compare (char *string, char *reversed);
//void readstring (char *str, int *n);

int main ()
{

  char string[] = {"rentner"}, reversed[10];
  int pal;

  //printf ("Number of characters: ");
  //scanf ("%d", &n);

  //string = (char *) calloc (n + 1, sizeof (char));

  //readstring (string, &n);

  reverse (string, reversed);

  pal = compare (string, reversed);

  if (pal)
    printf ("\n\nPalindrom.");

    else
      printf ("\n\nNot a palindrom.");

  //free (string);

  getchar ();
  return 0;

}


int compare (char *string, char *reversed)
{

  while (*string != '\0')               // vergleicht bis der 1. String zu Ende ist
  {

    if (*string != *reversed)        // vergleicht die Zeichen, wenn falsch wird abgebrochen                            
      return 0;

    string++;                              // die nächsten Zeichen werden verglichen
    reversed++;

  }

  return 1;                               // 1 wird zurückgegeben, wenn der String ein Palindrom ist

}


void reverse (char *string, char *reversed)
{

  int i;

  for (i = 0; *string != '\0'; i++, string++)           // nur Kleinbuchstaben
    *string = tolower (*string);

  string -= i;                                                    // wieder zurück zum 1. Zeichen

  for (i = 0; *string != '\0'; i++, string++);          // der 1. String läuft bis zum Ende durch

  string--;                                                       // aufs letzte Zeichen zurück (nicht \0!!!)

  while (i >= 0)                                                
  {
    *reversed = *string;                                    // der String wird rückwärts auf "reversed" kopiert
    string--;
    reversed++;
    i--;
  }

  *(reversed + 1) = '\0';                                    // Nullbyte setzen

}


/*
void readstring (char *str, int *n)                // Eingabe des Strings (nur mit Windows  :evil: )
{

  int pruef=0, i=0;

  printf ("\n\nInput:\n");

  while (i<*n && pruef==0)
  {

     *str = getche ();

     if (*str == 13)                       // Enter
     {
       pruef=1;
       (*n) = i;
     }

       else if (*str == 8)           // Backspace
       {

         if (i>0)
         {
           i--;
           str--;
         }

           else
             i=0;

         printf (" \b");

       }

         else
         {
           i++;
           str++;
         }

  }

  *str = '\0';

}
*/

__________________
EDIT:
Hab vergessen zu sagen, dass es nur bei _einem_ Beispiel nicht funzt. Bei Sachen wie "lol", "rentner" und "reliefpfeiler" gehts. Dann fiel mir nichts mehr ein und ich hab gegoogelt. Dieses Beispiel hier geht nicht:
EinNegermitGazellezagtimRegennie

Ich weiß, dass das ein bisschen an Rassismus grenzt, aber jedenfalls packt diesen String mein Programm nicht. *sich nicht erklären kann* :?

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Fault access; read of address nach Ende des Programmes

Beitrag von Xin » Do Nov 06, 2008 6:15 pm

dani93 hat geschrieben:
Xin hat geschrieben:zweise? Zwei Strings? Kann ich nix mit anfangen, sehe dafür keinen Quelltext.
Das sollte "zuweise" heißen :)
Okay, das hätt's auch sein können. ^^
dani93 hat geschrieben:

Code: Alles auswählen

  char string[] = {"rentner"}, reversed[10];
__________________
EDIT:
Hab vergessen zu sagen, dass es nur bei _einem_ Beispiel nicht funzt. Bei Sachen wie "lol", "rentner" und "reliefpfeiler" gehts. Dann fiel mir nichts mehr ein und ich hab gegoogelt. Dieses Beispiel hier geht nicht:
EinNegermitGazellezagtimRegennie

Ich weiß, dass das ein bisschen an Rassismus grenzt, aber jedenfalls packt diesen String mein Programm nicht. *sich nicht erklären kann* :?
Ich habe Dich eben auf reversed gedrückt und wiederhole das jetzt nochmal...
Schaust Du Dir es jetzt mal an?
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

nufan
Wiki-Moderator
Beiträge: 2558
Registriert: Sa Jul 05, 2008 3:21 pm

Re: Fault access; read of address nach Ende des Programmes

Beitrag von nufan » Do Nov 06, 2008 6:25 pm

Xin hat geschrieben:Ich habe Dich eben auf reversed gedrückt und wiederhole das jetzt nochmal...
Schaust Du Dir es jetzt mal an?
:shock: Ok ich seh's jetzt auch :)
"reversed" schreibt wirklich irgendwo im nirgendwo. Ich allokiere jetzt auch für "reversed" Speicher und gib ihn später wieder frei.
Ich habe ja schon öfters im Nirvana mit Zeigern hantiert (unabsichtlich natürlich :D ), aber das war ein Spezialfall. Normalerweise merke ich das ja mitten im Programm und sehe dann auch wo ich falsch bin.
Ich hatte auch schon ein Programm bei dem ich nach dem kompilieren einen Bluescreen hatte. Aber nur einmal. Ich habs danach 10 mal dasselbe Programm neu kompiliert und nichts passierte :D Tja, man lernt nie aus.

Problem gelöst, thx for help :)

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Fault access; read of address nach Ende des Programmes

Beitrag von Xin » Do Nov 06, 2008 6:43 pm

dani93 hat geschrieben:Ich hatte auch schon ein Programm bei dem ich nach dem kompilieren einen Bluescreen hatte. Aber nur einmal. Ich habs danach 10 mal dasselbe Programm neu kompiliert und nichts passierte :D Tja, man lernt nie aus.
Du wirst mit Deinem Programm einen Speicherbereich getroffen haben, der Windows zerschossen hat, welches anschließend als es etwas machen musste (kompilieren) zusammengebrochen ist.
dani93 hat geschrieben:Problem gelöst, thx for help :)
You're welcome.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Antworten