Komisches Verhalten von Arrays, die eigentlich eine andere Größe haben



  • Kann mir bitte jemand dieses Phänomen erklären? Ich habe ein Array, das eigentlich 200 Einheiten hat. Allerdings kann ich das Array auch 300 Einheiten groß Anzeigen lassen oder je nach dem auch noch in wesentlich größeren Einheiten. Was genau passiert dort, wenn ich die eigentliche Array Größe überschreite?

    #include <iostream>
    #include <stdio.h>
    #include <conio.h>
    #include <time.h>
    #include <windows.h>
    
    using namespace std;
    
    int main()
    {
    	int array[100][2];
    
    	int i, j;
    	int l = 0;
        for(i = 0; i < 100 ; i++)
        {
            for(j = 0; j < 2; j++)
            {
    			array[i][j] = rand() % 5 + 1;
    			printf("Nr. %d Array1 so wies gehoert[%d][%d] ist %d\n", l, i, j, array[i][j]);
    			l++;
    
    			Sleep(10);
    		}
    	}
    cout << "Durchlaeufe l: "<< l;
    	cout << "\n\n\n\n";
    
    	int a, b;
    	int c = 0;
        for(a = 0; a < 100 ; a++)
        {
            for(b = 0; b < 3; b++)
            {
    
    			printf("Nr. %d Array[%d][%d] ist %d\n", c, a, b, array[a][b]);
    	c++;
    	Sleep(10);
    		}
    	}
    	cout << "Durchlaeufe c: "<< c;
    	_getch();
    }
    


  • Array1234 schrieb:

    Was genau passiert dort, wenn ich die eigentliche Array Größe überschreite?

    Du liest wild im Speicher rum, der sich dort halt zufällig befindet. Mit Glück crashed sowas irgendwann. Mit Pech nicht und der Fehler bleibt unbemerkt. Noch besser wird's, wenn du nicht nur liest, sondern schreibst, dann hast du dir einen Buffer Overrun gebastelt...

    Du darfst nur auf Elemente eines Array zugreifen, die es auch wirklich gibt. Es obliegt deiner eigenen Verantwortung, dich daran zu halten; der Compiler wird dich nicht daran hindern, was falsch zu machen; Willkommen in C++ 😉 Sobald du außerhalb eines Arrays herumfuhrwerkst, hast du sog. undefiniertes Verhalten.


  • Mod

    Arrayzugriffe werden nicht auf Gültigkeit des Index geprüft. Liegt der Index außerhalb des Arrays, dann ist das Verhalten undefiniert. Das heißt, prinzipiell dürfte alles mögliche passieren, der Computer könnte beispielsweise deine Katze schwängern und das Geschirr spülen (außerdem ist dein Hund nun eine Katze).

    In der Praxis wird das Programm in der Regel einfach versuchen auf den Arbeitsspeicher hinter dem Array zuzugreifen. Was entweder völlig unspektakulär gelingen kann (das ist das, was du hier beobachtest) oder oft auch nicht (dann stürzt das Programm mit einer Zugriffsverletzung ab).



  • Wobei sein Fall mit dem zweidimensionalen Array etwas speziell ist. Wenn man ein int array[100][2] an Position array[x][3] ließt würde ich den Wert von Position array[x+1][0] erwarten. Bin mir aber nicht sicher ob das garantiert ist... Absichtlich machen würde ich sowas jedenfalls nicht.



  • sebi707 schrieb:

    Wobei sein Fall mit dem zweidimensionalen Array etwas speziell ist. Wenn man ein int array[100][2] an Position array[x][3] ließt würde ich den Wert von Position array[x+1][0] erwarten. Bin mir aber nicht sicher ob das garantiert ist...

    Nö, das ist undefiniertes Verhalten, all bets are off. Es wird in der Regel effektiv einfach auf das Element array[x+1][0] zugreifen, ja (weil die Adressberechnung mit den Inputs halt die entsprechende Adresse liefert), aber es könnte genausogut crashen, 42 liefern oder bedeuten, dass du Dienstag abends um 21:03 eine Lieferung Bleistiftspitzer bekommst...

    Im Allgemeinen ist es in C++ bereits undefiniertes Verhalten, die Adresse eines nicht existierenden Arrayelements überhaupt auch nur auszurechnen (einzige Ausnahme ist das erste Element hinter dem letzen, C++ garantiert, dass du einen Pointer auf dieses ausrechnen kannst, dereferenzieren darfst du den aber selbstverständlich nicht).



  • Ich wollte mal das Monty Hall Problem in C++ beweisen. Dadurch bin ich auf die Array Problematik gestoßen. Dann kann ich meinen Code wohl über den Haufen werfen. Lässt sich zwar prima kompelieren aber ist halt nunmal flasch. Weiß jemand sonst, wie ich das hinbekommen könnte?

    #include <iostream>
    #include <stdio.h>
    #include <conio.h>
    #include <time.h>
    #include <windows.h>
    
    using namespace std;
     int Tueren[100][3];
     int MeineErstwahl[1000];
     int ModeratorKannTuereAufdecken[100][2];
     int ModeratorDecktTuereAuf[100][2];
    
    int main()
    {
     srand(time(NULL));
     //Inizialisiert Türen
        int i, j;
        for(i = 0; i < 100 ; i++)
        {
            for(j = 0; j < 3; j++)
            {
                Tueren[i][j] = rand() % 3 + 1;
            }
        }
    
    	// Macht das jede Dreierreihe drei unterschiedliche Zahlen hat
    	int h, k;
        for(h = 0; h < 100 ; h++)
        {
            for(k = 0; k < 3; k++)
            {
                while(Tueren[h][k] == Tueren[h][k+1])
    			{
    				Tueren[h][k+1] = rand() % 3 + 1;
    			}
    			while(Tueren[h][k] == Tueren[h][k+2] || Tueren[h][k + 1] == Tueren[h][k+2])
    			{
    				Tueren[h][k+2] = rand() % 3 + 1;
    			}
            }
        }
    
    	// Inizialiesiert die Türe, die ich zuerst wähle
    
    	int z;
    	for(z = 0; z < 100; z++)
        {
    		MeineErstwahl[z] = rand() % 3 + 1;
        }
    
    	// Inizialisiert, welche Türen der Moderator zuerst öffnen kann!
    
    	int o, p;
    	int q = 0;
    	for(o = 0; o < 100; o++)
        {
            for(p = 0; p < 3; p++)
            {
    			if((Tueren[o][p] != 1) && (Tueren[o][p] != MeineErstwahl[o]))
    			{
    				ModeratorKannTuereAufdecken[o][q] = Tueren[o][p];
    
    				if(q == 0)
    				{
    					q++;
    				}
    
    			}
    		}
    		q--;
        }
    
    int u, t;
    
    for(u = 0; u < 100; u++)
    {
    	for(t = 0; t < 2; t++)
    	{
    		if((ModeratorKannTuereAufdecken[u][t] != 0) && (ModeratorKannTuereAufdecken[u][t + 1] != 0))
    		{
    			int n;
    			n = rand() % 2 + 4;
    
    				if(n == 4)
    				{
    					ModeratorDecktTuereAuf[u][t] = ModeratorKannTuereAufdecken[u][t];
    					ModeratorDecktTuereAuf[u][t + 1] = 0;
    				}
    				if(n == 5)
    				{
    					ModeratorDecktTuereAuf[u][t + 1] = ModeratorKannTuereAufdecken[u][t];
    					ModeratorDecktTuereAuf[u][t] = 0;
    				}
    
    		}
    	}
    
    }
    
    int a, b;
    for(a = 0; a < 100; a++)
    {
            for(b = 0; b < 3; b++)
            {
                printf("Tueren[%d][%d] = %d\n", a,b,Tueren[a][b]);
    			Sleep(1);
            }
    		printf("Meine Erstwahl ist: %d\n",  MeineErstwahl[a]);
    		printf("Moderator kann Tuere aufdecken: %d\n", ModeratorKannTuereAufdecken[a][b-3]);
    		printf("Moderator kann Tuere aufdecken: %d\n", ModeratorKannTuereAufdecken[a][b-2]); 
    
    		printf("Moderator deckt Tuere auf: %d\n", ModeratorDecktTuereAuf[a][b-3]);
    		printf("Moderator deckt Tuere auf: %d\n\n", ModeratorDecktTuereAuf[a][b-3]);
    }
    
        _getch();
    }
    

  • Mod

    Array1234 schrieb:

    Weiß jemand sonst, wie ich das hinbekommen könnte?

    Beispielsweise, indem du Code schreibst, der nicht über Arraygrenzen hinaus zugreift? Zwingt dich doch niemand dazu.


Anmelden zum Antworten