Run-Time Check Failure #2 - Stack around the variable was corrupted

Neonof

Mitglied
Hallo einmal,

ich arbeite gerade einmal dieses C-Tutorial durch.
Zum Thema Arrays (Schleifen) gab es nun folgende Aufgabe:

Schreibe ein Programm, dass den Benutzer auffordert, 10 Schulnoten als Kommazahlen einzugeben. Diese Zahlen sollen in einem Array zwischengespeichert werden. Im Anschluss berechnet das Programm die Summe und den Durchschnitt. Diese Daten werden am Bildschirm ausgegeben.

Die Aufgabenstellung habe ich folgendermaßen gelöst:

Code:
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>

int main() {
	file10();
	printf("\nAlle Programme wurden ausgef%chrt.\n", 129);
	system("Pause");
	return 0;
}

Code:
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>

int file10() {
	float noten[9], summe = 0;
	int i;

	for (i = 0; i <= 9; i++) {
		printf("Geben Sie die %d. Note ein: ", i + 1);
		scanf("%f", &noten[i]);
	}

	printf("\n\nDies sind die zuvor eingegebenen Noten:\n");

	for (i = 0; i < 9; i++) {
		printf("%.2f, ", noten[i]);
	}
	printf("%.2f\n\n", noten[i]);
	
	for (i = 0; i <= 9; i++) {
		summe += noten[i];
	}
	
	printf("Dies ist die Summe: %.2f\n", summe);
	printf("Und dies ist der Durchschnitt: %.2f\n", summe / 10);
	return 0;
}

Das Programm wird erfolgreich kompiliert, die Kommandozeile öffnet sich, man kann alle Werte eingeben und das Programm läuft zu Ende. Beim Beenden jedoch taucht diese Fehlermeldung auf:

Screenshot

Der Debugger unterbricht die Ausführung und die angezeigte Marke bleibt nach der return-Anweisung stehen:

Screenshot


Nun habe ich natürlich etwas gegooglet und stieß dabei auf diesen Thread, in dem diese Fehlermeldung schon einmal angesprochen wurde. Tobias erklärte dort, dass der Fehler lediglich bedeutet, dass ein Wert in eine Variable gespeichert werden soll, obwohl diese ihn nicht aufnehmen kann.
Der Ausführung nach sieht es für mich aus, als ob der Fehler beim "return 0;" liegt, doch das macht doch keinen Sinn, zumal es ja um das Array noten geht, oder? o.0
Auf dem zweiten Screenshot sieht man die Programmausführung und dass alle Variablen korrekt berechnet wurden.

Ich danke schon einmal für Hilfe :)
 

sheel

I love Asm
Hi

Gründe für solche Fehler gibts viele, aber ja, in deinem Fall ist es ein Array das zu klein ist.

"float noten[9]" hat 9 Elemente, die Indexe sind 0 bis 8. Du willst ja 10 Elemente, Index 0 bis 9. Manche deiner Schleifen gehen schon jetzt bis Index 9 inklusive, und das ist das Problem (also der Zugriff auf [9]).

(Und eine Schleife hat nur <9 statt <=9 obwohl es für 10 Elemente ja <=9 sein sollte).

Es ist wichtig zu verstehen, dass es in C (und C++) "undefined behaviour" gibt: Code der falsch ist, oft vom Compiler aber nicht gemeldet wird, und beim Ausführen beliebig seltsame Wirkungen hat:
Manchmal bekommt man solche Fehler an der richtigen Stelle, manchmal davor oder danach (wie bei dir), manchmal geht alles gut, und manchmal macht das Programm einfach was komplett falsches, aber ohne Fehlermeldung (Variablenwerte die sich grundlos ändern usw.).
Die falsche Stelle im Code zu finden kann bei größeren Programmen ziemlich schwer werden ... beim Schreiben schon alles übergenau prüfen ist leichter.

edit:
Warum es UB gibt bzw. das vom Compiler nicht geprüft wird?
Einen Compiler zu machen, der solche Fehler wirklich 100%-ig erkennt, ist prinzipiell einfach unmöglich.

zB. für diesem Fall, also Zugriff über das Arrayende hinaus: Die Bestimmung, auf welchen Arrayindex man zugreifen will, kann beliebig komplex werden. In deinem Fall ist es einfach die Variable i, die in der Schleife immer erhöht wird. Man könnte aber genau so gut einen Code schreiben, der über einen Satelliten die aktuellen Koordinaten auf unserem Planet bestimmt, davon die Wurzel nimmt, und das dann als Arrayindex verwendet. Der Compiler sollte das Programm nicht ausführen, darf den Satellit also nicht verwenden ... und außerdem kann man die eigene Position ja immer wieder ändern, der Compiler kann die Prüfung nur einmal am Anfang machen.

Was man machen könnte: Den Compiler beim Programmerstellen bei jedem Arrayzugriff zuerst einen Prüfcode einfügen lassen, ob der Index in den erlaubten Limits ist, und sonst einen Fehler ausgeben. In dem Fall bekommt man zwar noch immer keinen Compilerfehler, aber eben einen Fehler während der Programmausführung (einen garantierten Fehler, keine Chance für andere Seltsamkeiten).
Sprachen wie Java machen das auch so; bei C ist das aber absichtlich nicht der Fall: Es hat nämlich auch einen Vorteil, und zwar eine schnellere Ausführung vom Programm (der Preis ist eben, dass der Programmierer mehr aufpassen muss).
 
Zuletzt bearbeitet: