Arrayüberlauf / interne Speicherverwaltung
-
Hallo,
habe folgendes Miniprogramm:
Frage dazu: Wenn die anzahl größer als 20 ist, wird der Speicher hinter
dem Array verwendet um die Zahlen zu speichern.
Da es ein int-Array ist, reserviert er doch 20 * 4 Byte,
wenn ich Werte über 24 angebe durchläuft er das Array bis 24
und warum kann ich überhaupt auf Werte größer 20 zugreifen?#include <iostream> #include <conio.h> #include <stdlib.h> using namespace std; int main() { int anzahl; time_t t; time(&t); srand((unsigned int)t); /* Zufallsgenerator initialisieren */ cout<<"Bitte geben sie die Anzahl der zu speichernden Zahlen: "<<endl; cin>> anzahl; int array[20]; for(int i = 1; i <= anzahl; i++) { array[i] = rand() % 6 + 1; if(i % 10 == 0) { cout<< array[i] <<endl; } else { cout<< array[i]; } } cout<< endl; cout<< "12 % 10 ist :" << 12 % 10; getch(); return 0; }gruß alex
-
C war eher auf Geschwindigkeit ausgelegt, deshalb werden Bereichsüberschreitungen auch nicht überprüft (sowas nennt sich "undefiniertes Verhalten"). Das heißt, du mußt schon selber dafür sorgen, daß du nicht außerhalb des reservierten Bereiches schreibst.
C++ hat die Array-Verarbeitung weitgehend von C geerbt (also inklusive der nicht vorhandenen Index-Überprüfung). Aber in C++ gibt es neue Containerklassen (für dich interessant sind sicher vector<> oder deque<>), die mitwachsen können - und auch eine optionale Bereichskontrolle bieten (wenn du at() anstelle von op[] für den Elementzugriff verwendest, schmiert dein Programm kontrolliert ab ;)).
-
alexC++ schrieb:
Da es ein int-Array ist, reserviert er doch 20 * 4 Byte,
wenn ich Werte über 24 angebe durchläuft er das Array bis 24
und warum kann ich überhaupt auf Werte größer 20 zugreifen?ein
int foo[ 20 ]; // reserviert 20 * sizeof( int ) Bytes auf dem Stack.foo dereferenziert auf die Anfangsadresse des Speicherbereichs. Du kannst auf
foo[ 20 ]; // , das 21. Element, zugreifen weil das nichts anderes bedeutet als *( foo + 20 * sizeof( int ) ); // und du damit auf den Speicher an dererrechneten Adresse zugreifst. C und C++ prüfen nicht auf ein Überschreiten von Arraygrenzen. Das Verhalten dabei ist natürlich undefiniert und geht nur gut, wenn das Betriebssystem dir nicht dazwischenspuckt (dh. idR. das Du auf den Deinem Programm zugesprochenen Datenspeicher (vgl. Data Segment) zugreifen kannst, ohne ein paar auf die Finger zu bekommen.
greetz, Swordfish
/edit: oje, 5 min zu spät!?
-
int foo[ 20 ]; // reserviert 20 * sizeof( int ) Bytes auf dem Stack.
Ich dachte das ein Array ein Verweistyp ist und deshalb Speicher vom
Heap anfordert.Ok das ist mir alles schon klar, wo ich nicht durchblicke ist,
dass er, wenn ich 30 für die anzahl angebe, nur bis 23 läuft.
Wenn es keine Bereichsüberprüfung gibt, müsste er doch dann bis 30 laufen.
-
alexC++ schrieb:
int foo[ 20 ]; // reserviert 20 * sizeof( int ) Bytes auf dem Stack.
Ich dachte das ein Array ein Verweistyp ist und deshalb Speicher vom
Heap anfordert.Nein, vom Heap bekommst du nur Speicher, wenn du ihn mit new oder malloc() anforderst. Im Gegensatz zu Java arbeitet C(++) deutlich mehr mit dem Stack

Ok das ist mir alles schon klar, wo ich nicht durchblicke ist,
dass er, wenn ich 30 für die anzahl angebe, nur bis 23 läuft.
Wenn es keine Bereichsüberprüfung gibt, müsste er doch dann bis 30 laufen.Wie Swordfish schon sagt, geht das "nur gut, wenn das Betriebssystem dir nicht dazwischenspuckt" - und offenbar hast du bei der 23 den Punkt erreicht, wo du aus "deinem" Stack-Bereich rausgeflogen bist (hinter dem Array steht auf jeden Fall noch der 'time_t t', sowie eventuell noch einige interne VErwaltungsdaten für die Funktion).
-
Was ist ein "Verweistyp"? Ich kenne nur "Typ"

(Ich weiss schon was das ist aber dem OP ist scheinbar nicht klar, dass es in C++ keine Verweis- und Werttypen gibt, sondern einfach nur Typen im Sinne von Werttypen.)
@OP:
Wenn Du kein "new" siehst, landet etwas auch nicht auf dem Heap. Was eine Klasse intern evtl. auf dem Heap konstruiert ist eine andere Sache.
-
okay
ich sollte nicht so viel mischen C# / C++