Zum Inhalt springen

Speicherzugriffsfehler


Empfohlene Beiträge

Geschrieben

Hallo,

Ich bekomme bei einem C Programm an einer bestimmten Stelle in einer Funktion immer einen Speicherzugriffsfehler. Das Problem an der Sache ist, wenn ich die Funktion mehrmals hintereinander aufrufe dann klappt sie ohne Probleme. Habe da aber ein Menü zu "programmiert" und jetzt kommt an einer Stelle eben immer der Fehler...

Das C Programm ist ein Krawattenhalter, die Funktion fügt eine neue Krawatte immer an der letzten Position ein und setzt den Zeiger der aktuellen Krawatte *k auf diese. Das ganze ist eine einfach verkettete Liste und war schon unglaublich stolz auf mich das es Funktioniert hat, nur nachdem ich die Funktion jetzt aus dem Menü aufrufe eben nicht mehr!

main.c


int main() {


	Krawatte *k = 0;

	char menuInput = '\0';


	char insColor;

	char insPattern;


	////////// Wenn ich die nächsten Zeile auskommentiere, dafür das Menü kommentiere läuft alles wie es soll

	/*

	Daten d1, d2;

	d1.color = ROT;

	d1.pattern = KARIERT;


	d2.color = BLAU;

	d2.pattern = GESTREIFT;


	einfuegen(&k, d1);

	einfuegen(&k, d2);

	einfuegen(&k, d1);

	einfuegen(&k, d2);


	ausgabe(&k);


	printf("Fertig");*/

	//////////


	while (menuInput != 'q') {


		printf("Menu\n");

		printf("----\n");

		printf("Press [i] to insert\n");

		printf("Press [q] to quit\n");

		printf("Press [p] to print\n");

		printf("Eingabe: ");

		scanf("%1s", &menuInput);


		switch(menuInput) {


			case 'i':

				//Krawatte einfügen

				printf("Krawatte einfuegen:\n");

				Daten *insData = (Daten *) malloc(sizeof(Daten));

				//Farbe

				printf("Farbe:\n");

				printf("Rot [r]\n");

				printf("Gelb [g]\n");

				printf("Blau [b]\n");

				printf("Eingabe: ");

				scanf("%1s", &insColor);

				switch(insColor) {

					case 'r':

						insData->color = ROT;

						break;

					case 'g':

						insData->color = GELB;

						break;

					case 'b':

						insData->color = BLAU;

						break;

					default:

						insData->color = ROT;

				}

				//Muster

				printf("\nMuster:\n");

				printf("Kariert [k]\n");

				printf("Gestreift [s]\n");

				printf("Gepunktet [p]\n");

				printf("Eingabe: ");

				scanf("%1s", &insPattern);

				switch(insPattern) {

					case 'k':

						insData->pattern = KARIERT;

						break;

					case 's':

						insData->pattern = GESTREIFT;

						break;

					case 'p':

						insData->pattern = GEPUNKTET;

						break;

					default:

						insData->pattern = KARIERT;

				}


				printf("\n");

				einfuegen(&k, *insData);

				free(insData);

				break;

			case 'p':

				ausgabe(&k);

				break;


		}


	}

	return 0;


}

listType.h

        typedef enum farbe {ROT, GELB, BLAU} Farbe;

	typedef enum muster {KARIERT, GESTREIFT, GEPUNKTET} Muster;


	typedef struct Daten {


		Farbe color;

		Muster pattern;


	} Daten;


	typedef struct Krawatte {


		Daten data;

		struct Krawatte *nextTie;


	} Krawatte;

listType.c

void einfuegen(Krawatte **k, Daten d) {

	//Neue Krawatte erstellen

	Krawatte *newTie = (Krawatte *) malloc(sizeof(Krawatte));

	if (newTie == NULL) {

		printf("Fehler: Kein Speicher mehr vorhanden!\n");

		exit(1);

	}


	//Überprüfen ob schon eine Krawatte im Halter exisitiert

	if (*k == NULL) {

		newTie->data = d;


		//Erste und letzte Krawatte im Halter

		newTie->nextTie = newTie;

		*k = newTie;

	}

	else {

		Krawatte *lastTie = (Krawatte *) malloc(sizeof(Krawatte));

		lastTie = *k;

		printf("lastTie: %p\n", lastTie);

		printf("lastTie->nextTie: %p\n", lastTie->nextTie);

		printf("*k: %p\n", *k);


		//Suche letzte Krawatte im Halter

		while (lastTie->nextTie != *k) {

			[COLOR="red"]//IN DER NÄCHSTEN ZEILE LIEGT DER SPEICHERZUGRIFFSFEHLER!!

			lastTie = lastTie->nextTie;[/COLOR]

		}

		newTie->data = d;


		//Füge Krawatte an letzter Position ein und setze Zeiger auf neu eingefügte Krawatte

		newTie->nextTie = *k;

		lastTie->nextTie = newTie;

		*k = newTie;


		//Speicher freigeben

		free(lastTie);

	}


	/*

	printf("\n\n----\n");

	printf("newTie: %p\n", newTie);

	printf("newTie->nextTie: %p\n", newTie->nextTie);

	printf("*k: %p\n", *k);

	printf("----\n\n");

	*/


	printf("Krawatte wurde eingefuegt:\n");

	ausgabeKrawatte(newTie->data.color, newTie->data.pattern);

}

Ein paar Sachen waren vorgegeben: Die Structs inkl Aufbau und Namen und die Signatur von einfuegen. Der Rest ist verhandelbar...;)

Geschrieben

Das malloc/free-Paar im else-Block der einfuegen-Funktion ist falsch.

Krawatte *lastTie = (Krawatte *) malloc(sizeof(Krawatte));
Hier holst du nochmal Speicher für eine Krawatte. Warum überhaupt?
lastTie = *k;
Hier verbiegst du den Zeiger lastTie auf den Listenanfang. Damit hast du keinen Zeiger mehr, der auf den gerade reservierten Speicher zeigt -> Speicherleck.
free(lastTie);

Da lastTie auf deinen alten Listenanfang zeigt, löschst du hier eine Krawatte aus deiner Liste. Der Vorgänger verweist allerdings noch darauf, darum fliegt es dir um die Ohren, wenn du das nächste Mal die Liste durchgehst.

Geschrieben

Ja das kann schon sein, aber habe nur vergessen das wieder rauszunehmen, habe es Testweise eingefügt, den Fehler gab es schon vorher, bzw gibt es jetzt wieder. So sieht der else Block eigentlich aus:


else {

		Krawatte *lastTie = *k;

		printf("lastTie: %p\n", lastTie);

		printf("lastTie->nextTie: %p\n", lastTie->nextTie);

		printf("*k: %p\n", *k);


		//Suche letzte Krawatte im Halter

		while (lastTie->nextTie != *k) {

			printf("Suche nachechste Krawatte...\n");

			lastTie = lastTie->nextTie;

		}

		newTie->data = d;


		//Füge Krawatte an letzter Position ein und setze Zeiger auf neu eingefügte Krawatte

		newTie->nextTie = *k;

		lastTie->nextTie = newTie;

		*k = newTie;

	}

Vielen Dank schon mal:)

Geschrieben

Mit diesem Code tritt das Problem bei mir nicht mehr auf.

Allerdings hast du noch einen Fehler beim Einlesen der Benutzereingaben: Wenn du mit %1s einliest, brauchst du ein char-Array mit mindestens zwei Elementen, weil automatisch eine Nullterminierung angehängt wird. Alternativ kannst du auch mit %c einlesen.

Geschrieben

Ja das Problem daran war das dadurch manchmal scanf übersprungen wurde. (Hab auch dazu was in dem MSDN nachgelesen - programmiere zwar mit Linux aber durch %1s war das Problem dann trotzdem gelöst).

Aber mit dem Code oben klappts bei dir? Theoretisch sollte es bei mir ja auch. Wie man in der main.c sieht, wenn ich den oberen auskommentierten Code benutze, also einfach ein paar mal hintereinander einfuegen(x, y) aufrufe, funktioniert es. Durch das Menü kommt in der Funktion der Speicherzugriffsfehler...

Geschrieben

Ok gesagt getan. Menü funktioniert immer noch, Fehler leider immer noch da:( Aber woran kann es denn bitte liegen das es ohne Menü funktioniert, mit aber nicht? Da muss das Menü doch irgendwo am Speicher rumwurschteln oder?


int main() {


	Krawatte *k = 0;

	char menuInput[1];

	menuInput[0] = '\0';


	char insColor[1];

	char insPattern[1];


	while (menuInput[0] != 'q') {


		printf("Menu\n");

		printf("----\n");

		printf("Press [i] to insert\n");

		printf("Press [q] to quit\n");

		printf("Press [p] to print\n");

		printf("Eingabe: ");

		scanf("%1s", menuInput);


		switch(menuInput[0]) {


			case 'i':

				//Krawatte einfügen

				printf("Krawatte einfuegen:\n");

				Daten *insData = (Daten *) malloc(sizeof(Daten));

				//Farbe

				printf("Farbe:\n");

				printf("Rot [r]\n");

				printf("Gelb [g]\n");

				printf("Blau [b]\n");

				printf("Eingabe: ");

				scanf("%1s", insColor);

				switch(insColor[0]) {

					case 'r':

						insData->color = ROT;

						break;

					case 'g':

						insData->color = GELB;

						break;

					case 'b':

						insData->color = BLAU;

						break;

					default:

						insData->color = ROT;

				}

				//Muster

				printf("\nMuster:\n");

				printf("Kariert [k]\n");

				printf("Gestreift [s]\n");

				printf("Gepunktet [p]\n");

				printf("Eingabe: ");

				scanf("%1s", insPattern);

				switch(insPattern[0]) {

					case 'k':

						insData->pattern = KARIERT;

						break;

					case 's':

						insData->pattern = GESTREIFT;

						break;

					case 'p':

						insData->pattern = GEPUNKTET;

						break;

					default:

						insData->pattern = KARIERT;

				}


				printf("\n");

				einfuegen(&k, *insData);

				free(insData);

				break;

			case 'p':

				ausgabe(&k);

				break;


		}


	}

	return 0;

}

Geschrieben (bearbeitet)

Oh mein Gott das war echt doof von mir:D Dachte wenn ich ein Array erstelle mit [1] Elementen erzeugt der 0 und 1...Kurz drüber nachgedacht, korrigiert und jetzt funktioniert es;) Gibt wahrscheinlich einen guten Grund warum der Speicherfehler erst später auftritt aber ist ja schrecklich wenn man nach Fehlern suchen will.

Vielen vielen Dank!

Edit: Weil ich nicht der Typ bin der sich alles vorkauen lässt und gerne selber die Fehler findet (Höhö): Wie kann ich Speicherzugriffsfehler debuggen? Benutze Eclipse oder die Konsole unter Debian 6

Bearbeitet von demo88

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...