Untypischer Laufzeitfehler durch malloc()



  • @Swordfish sagte in Untypischer Laufzeitfehler durch malloc():

    Ein vollständiges kompilierbares Programm wäre schon super.

    Moin moin 🙂

    #include <stdio.h>
    #include <stdlib.h>
    #include <termio.h>
    #include <math.h>
    #include <time.h>
    #define KEY_UP		'w'
    #define KEY_DOWN	's'
    #define KEY_LEFT	'd'
    #define KEY_RIGHT	'a'
    #define BLANK		0
    #define HEAD		1
    #define TAIL		2
    #define FOOD		3
    
    int gameover	= 0;
    int points		= 0;
    int width		= 100;
    int height		= 100;
    int tailcount	= 0;
    
    struct position{
    	int x;
    	int y;
    } pos;
    
    static struct termio savemodes;
    static int havemodes = 0;
    int tty_break() {
            struct termio modmodes;
            if(ioctl(fileno(stdin), TCGETA, &savemodes) < 0)
                    return -1;
            havemodes = 1;
            modmodes = savemodes;
            modmodes.c_lflag &= ~ICANON;
            modmodes.c_cc[VMIN] = 1;
            modmodes.c_cc[VTIME] = 0;
            return ioctl(fileno(stdin), TCSETAW, &modmodes);
    }
    
    void initalFeld(int *feld, int count, int wert){
    	int cnt;
    	for(cnt=0; cnt<count; cnt++){
    		*(feld+cnt) = wert;
    	}
    }
    
    void initalTail(struct position *tail){
    	int cnt=0;
    	struct position myPos;
    	myPos.x=-1;
    	myPos.y=-1;
    //	printf("Fehler");
    	for(cnt=0; cnt <= width * height; cnt++){
    		*(tail + cnt) = myPos;
    	}
    }
    
    void move(int key){
    	switch(key){
    		case KEY_DOWN:
    			if(pos.y >= height -1) pos.y = 0;
    			else ++pos.y;
    			break;
    		case KEY_UP:
    			if(pos.y <= 0) pos.y = height -1;
    			else --pos.y;
    			break;
    		case KEY_LEFT:
    			if(pos.x >= width -1) pos.x = 0;
    			else ++pos.x;
    			break;
    		case KEY_RIGHT:
    			if(pos.x <= 0) pos.x = width -1;
    			else --pos.x;
    	}
    }
    
    void printFeld(int *feld){
    	int x;
    	int y;
    	int figur;
    	fprintf(stdout, "\033[2J");
    	fprintf(stdout, "\033[1;1H");
    	printf("\nsnake v%d.%d\n(%d x %d)\n", \
    		snake_VERSION_MAJOR, snake_VERSION_MINOR, width, height);
    	for(y=0; y < height + 2; y++){
    		printf("\n|");
    		for(x=0; x < width; x++){
    			if(y==0 || y==height +1)printf("-");
    			else{
    				figur = *(feld + (x*height +y-1));
    				switch(figur){
    					case BLANK: printf(" "); break;
    					case HEAD : printf("@"); break;
    					case TAIL : printf("*"); break;
    					case FOOD : printf("X"); break;
    				}
    			}
    		}
    		printf("|");
    	}
    	printf("\n\n%d Punke\n",points);
    }
    
    int setFeld(int *feld, struct position *tail, int befor){
    	int ret = 1;
    	int cnt = 0;
    	int randx;
    	int randy;
    	static int hasFood = 0;
    	struct position mypos;
    	if(befor){
    		if(! hasFood){
    			*(feld + (pos.x * height + pos.y)) = BLANK;
    			if(tailcount > 0){
    				mypos = *tail;
    				*(feld + (mypos.x * height + mypos.y)) = BLANK;
    				*(feld + (pos.x * height + pos.y)) = TAIL;
    				if(tailcount > 1){
    					while(cnt < tailcount -1){
    						*(&tail[cnt]) = *(&tail[cnt+1]);
    						++cnt;
    					}
    					*(tail + tailcount -1) = pos;
    				}else if(tailcount == 1) *tail = pos;			
    			}
    		}else{
    			*(feld + (pos.x * height + pos.y)) = TAIL;
    			hasFood = 0;
    		}
    	}
    	else{
    		int figur = *(feld + (pos.x * height + pos.y));
    		if(figur == FOOD){
    			*(tail + tailcount) = pos;
    			++tailcount;
    			hasFood = 1;
    			points += 10;
    			do{
    				randx=rand() % width;
    				randy=rand() % height;
    			}while(*(feld + (randx * height + randy)) != BLANK);
    			*(feld + (randx * height + randy)) = FOOD;
    		}else if(figur == TAIL) ret = 0;
    		*(feld + (pos.x * height + pos.y)) = HEAD;
    	}
    	return ret;
    }
    
    void resetGame(int *feld, struct position *tail){
    	points = 0;
    	tailcount = 0;
    	initalFeld(feld, width * height, BLANK);
    	initalTail(tail);
    	pos.x = width / 2;
    	pos.y = height / 2;
    	*(feld + (pos.x * height + pos.y)) = HEAD;
    	*(feld + (pos.x * height + pos.y - 2)) = FOOD;
    }
    
    int main(int argc, char *argv[]){
    	char key = 'w';
    	char gemeOverkey;
    	int cnt;
    	int **feld;
    	struct position *tail;/*[width * height + 1];*/
    	if(argc > 2){
    		width=atoi(argv[1]);
    		height=atoi(argv[2]);
    
    		feld = malloc(width * sizeof(int));
    		for(cnt=0; cnt<width; cnt++)feld[cnt]=malloc(height * sizeof(int));
    		tail = (struct position *)malloc((width * height) *(sizeof(struct position)));
    	}else{
    		printf("Aufruf mit 'snake breite hoehe' max: 'snake 100 100'\n");
    		return 0;
    	}
    	resetGame(&feld[0][0],tail);
    	srand( (unsigned int) time(NULL) );
    	tty_break();
    	while(key != 'x'){
    		printFeld(&feld[0][0]);
    		setFeld(&feld[0][0],tail,1);
    		key = getchar();
    		move(key);
    		if(! setFeld(&feld[0][0],tail,0) || points == width * height * 10 - 20){
    			if(points == width * height * 10 - 20)
    				printf("\nSie haben gewonnen !");
    			else
    				printf("\nSie haben sich in den Schwanz gebissen !");
    			printf("\nnochmal j/n ?\n");
    			gemeOverkey = getchar();
    			if(gemeOverkey == 'j') resetGame(&feld[0][0],tail);
    			else if(gemeOverkey == 'n')break;
    		}
    	}
    	printf("\ndanke fuers spielen\n");
    	return 0;
    

    ist eine weiterentwicklung von
    einem c-tutorial Link Text



  • @EL-europ sagte in Untypischer Laufzeitfehler durch malloc():

     void initalFeld(int *feld, int count, int wert){
    	int cnt;
    	for(cnt=0; cnt<count; cnt++){
    		*(feld+cnt) = wert;
    	}
    }
    

    Du hast hier für feld kein zweidimensionales Array in dem alle Elemente direkt hintereinander im Speicher liegen.

    2D-Array int foo[][]{ { 1, 2, 3 }, { 4, 5, 6 } } starting at &foo[0]:

    1, 2, 3, 4, 5, 6
    Visualized:

    +------+
    | foo  |
    +------+ 
    |  1   |
    |  2   |
    |  3   |
    |  4   |
    |  5   |
    |  6   |
    +------+ 
    

    Dein Zeiger auf Zeiger auf int:

    int foo = malloc(2 * sizeof(int*));  // beachte das sternchen
    for (size_t i = 0; i < 2; ++i)
        foo[i] = malloc(3 * sizeof(int));
    int value = 1;
    for (size_t y = 0; y < 2; ++y)
        for (size_t x = 0; x < 3 ++x)
            foo[y][x] = value++;
    
    
                           +------+
                      +--> | int  |
                      |    +------|
                      |    |  1   |
                      |    |  2   |
                      |    |  3   |
    +---------+       |    +------+
    | foo[0] -|-------+
    | foo[1] -|-------+    +------+
    +---------+       +--> | int  |
                           +------+
                           |  4   |
                           |  5   |
                           |  6   |
                           +------+
    


  • @Swordfish
    Super, danke für die schnelle Antwort. Ich werd nach dem Schlafen versuchen sie zu Verstehen und dann zu implementieren. Dann geb ich hier noch nen Kommentar dazu ab. Aller Vorraussicht noch heute am mittag.

    😴



  • @EL-europ sagte in Untypischer Laufzeitfehler durch malloc():

    for(cnt=0; cnt <= width * height; cnt++)
    

    Das <= sollte wohl besser < sein.
    So wie die Schleife da steht läuft die bis inklusive width * height, sollte aber bis exklusive width * height laufen weil ja bei 0 angefangen wird.
    Also bei beispielsweise width = height = 2 würde die Schleife von 0 bis inklusive 4 laufen, also 5 mal. Sollte aber nur 4 mal laufen.
    Rest hab ich mir nicht angesehen.

    Um solche Fehler zu finden eignen sich tools wie Valgrind oder Address Sanitizer. Anleitungen wie man diese verwendet sollten sich leicht ergoogeln lassen.



  • @hustbaer sagte in Untypischer Laufzeitfehler durch malloc():

    So wie die Schleife da steht läuft die bis inklusive width * height, sollte aber bis exklusive width * height laufen weil ja bei 0 angefangen wird.
    Also bei beispielsweise width = height = 4 würde die Schleife von 0 bis inklusive 4 laufen, also 5 mal. Sollte aber nur 4 mal laufen.

    Du meinst "würde die Schleife von 0 bis inklusive 16 laufen, also 17 mal. Sollte aber nur 16 mal laufen."!?!



  • Danke @hustbaer 🙏🏻 das war der Fehler. Beim Ändern auf dynamischen Speicher hab ich vergessen das ich +1 Feld brauche 😵

    Danke nochmal das du dir das angesehen hast!



  • Ich will dich ja nicht nerven, aber

    @EL-europ sagte in Untypischer Laufzeitfehler durch malloc():

    		feld = malloc(width * sizeof(int));
    		for(cnt=0; cnt<width; cnt++)feld[cnt]=malloc(height * sizeof(int));
    

    ist immer noch Mist.

    Erstens funktioniert das nur zufällig wenn sizeof int und sizeof int* gleich sind und zweitens hast Du damit keinen zusammenhängenden Speicherbereich (außer evtl. Zufällig) auf den Du mit

    @EL-europ sagte in Untypischer Laufzeitfehler durch malloc():

    	for(cnt=0; cnt<count; cnt++){
    		*(feld+cnt) = wert;
    	}
    

    in initalFeld() zugreifen könntest.



  • @Swordfish
    Danke dir das du das auch angesehen hast. Und ich bin mit dir das dieses 2d-feld falsch iniziiert wurde, aber bei der Ausführung ist es trotzdem richtig iniziiert, auch wenn ich von 0 verschiedene Werte nehme wird das Feld richtig dargestellt.
    Ich vermute der Fehler viel nicht auf weil keine verschiedenen Werte iniziiere sondern nur gleiche,

    Danke dir auch nochmal



  • @Swordfish
    Die Speicheralloziierung ist doch Richtig oder? Die hab ich ausm Grundkurs von Jürgen Wolf. Die iniziierung des Feldes ist aber Falsch gewesen! Hab ich dich da Richtig verstanden?


  • Mod

    @EL-europ sagte in Untypischer Laufzeitfehler durch malloc():

    @Swordfish
    Die Speicheralloziierung ist doch Richtig oder? Die hab ich ausm Grundkurs von Jürgen Wolf. Die iniziierung des Feldes ist aber Falsch gewesen! Hab ich dich da Richtig verstanden?

    Argh! Da bist du leider reingefallen:
    https://www.c-plusplus.net/forum/topic/272350/warnung-bücher-von-jürgen-wolf-zu-c-und-c-zum-lernen-ungeeignet-weil



  • Du greifst auf Speicher zu der Dir nicht gehört.

    valgrind output:

    ==296== Memcheck, a memory error detector
    ==296== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
    ==296== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
    ==296== Command: ./a.out 60 20
    ==296== Parent PID: 13
    ==296== 
    ==296== Invalid write of size 8
    ==296==    at 0x109B2E: main (in /mnt/c/Users/Swordfish/a.out)
    ==296==  Address 0x4a48130 is 0 bytes after a block of size 240 alloc'd
    ==296==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==296==    by 0x109AF6: main (in /mnt/c/Users/Swordfish/a.out)
    ==296== 
    ==296== Invalid write of size 4
    ==296==    at 0x1093C5: initalFeld (in /mnt/c/Users/Swordfish/a.out)
    ==296==    by 0x1099F9: resetGame (in /mnt/c/Users/Swordfish/a.out)
    ==296==    by 0x109B76: main (in /mnt/c/Users/Swordfish/a.out)
    ==296==  Address 0x4a481c0 is 0 bytes after a block of size 80 alloc'd
    ==296==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==296==    by 0x109B2D: main (in /mnt/c/Users/Swordfish/a.out)
    ==296== 
    ==296== Invalid write of size 8
    ==296==    at 0x109419: initalTail (in /mnt/c/Users/Swordfish/a.out)
    ==296==    by 0x109A05: resetGame (in /mnt/c/Users/Swordfish/a.out)
    ==296==    by 0x109B76: main (in /mnt/c/Users/Swordfish/a.out)
    ==296==  Address 0x4a4c8b0 is 0 bytes after a block of size 9,600 alloc'd
    ==296==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==296==    by 0x109B5C: main (in /mnt/c/Users/Swordfish/a.out)
    ==296== 
    ==296== Invalid write of size 4
    ==296==    at 0x109A58: resetGame (in /mnt/c/Users/Swordfish/a.out)
    ==296==    by 0x109B76: main (in /mnt/c/Users/Swordfish/a.out)
    ==296==  Address 0x4a48af8 is 8 bytes before a block of size 80 alloc'd
    ==296==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==296==    by 0x109B2D: main (in /mnt/c/Users/Swordfish/a.out)
    ==296== 
    ==296== Invalid write of size 4
    ==296==    at 0x109A86: resetGame (in /mnt/c/Users/Swordfish/a.out)
    ==296==    by 0x109B76: main (in /mnt/c/Users/Swordfish/a.out)
    ==296==  Address 0x4a48af0 is 16 bytes before a block of size 80 alloc'd
    ==296==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==296==    by 0x109B2D: main (in /mnt/c/Users/Swordfish/a.out)
    ==296== 
    ==296== Invalid read of size 4
    ==296==    at 0x109620: printFeld (in /mnt/c/Users/Swordfish/a.out)
    ==296==    by 0x109BBB: main (in /mnt/c/Users/Swordfish/a.out)
    ==296==  Address 0x4a481c0 is 0 bytes after a block of size 80 alloc'd
    ==296==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==296==    by 0x109B2D: main (in /mnt/c/Users/Swordfish/a.out)
    ==296== 
    ==296== Invalid write of size 4
    ==296==    at 0x10972E: setFeld (in /mnt/c/Users/Swordfish/a.out)
    ==296==    by 0x109BD6: main (in /mnt/c/Users/Swordfish/a.out)
    ==296==  Address 0x4a48af8 is 8 bytes before a block of size 80 alloc'd
    ==296==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==296==    by 0x109B2D: main (in /mnt/c/Users/Swordfish/a.out)
    ==296== 
    ==296== Invalid read of size 4
    ==296==    at 0x1098A2: setFeld (in /mnt/c/Users/Swordfish/a.out)
    ==296==    by 0x109C04: main (in /mnt/c/Users/Swordfish/a.out)
    ==296==  Address 0x4a48af4 is 12 bytes before a block of size 80 alloc'd
    ==296==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==296==    by 0x109B2D: main (in /mnt/c/Users/Swordfish/a.out)
    ==296== 
    ==296== Invalid write of size 4
    ==296==    at 0x1099A3: setFeld (in /mnt/c/Users/Swordfish/a.out)
    ==296==    by 0x109C04: main (in /mnt/c/Users/Swordfish/a.out)
    ==296==  Address 0x4a48af4 is 12 bytes before a block of size 80 alloc'd
    ==296==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==296==    by 0x109B2D: main (in /mnt/c/Users/Swordfish/a.out)
    ==296== 
    
    valgrind: m_mallocfree.c:305 (get_bszB_as_is): Assertion 'bszB_lo == bszB_hi' failed.
    valgrind: Heap block lo/hi size mismatch: lo = 304, hi = 77894656.
    This is probably caused by your program erroneously writing past the
    end of a heap block and corrupting heap metadata.  If you fix any
    invalid writes reported by Memcheck, this assertion failure will
    probably go away.  Please try that before reporting this as a bug.
    
    
    host stacktrace:
    ==296==    at 0x58046FFA: ??? (in /usr/lib/x86_64-linux-gnu/valgrind/memcheck-amd64-linux)
    ==296==    by 0x58047127: ??? (in /usr/lib/x86_64-linux-gnu/valgrind/memcheck-amd64-linux)
    ==296==    by 0x580472CB: ??? (in /usr/lib/x86_64-linux-gnu/valgrind/memcheck-amd64-linux)
    ==296==    by 0x580514B4: ??? (in /usr/lib/x86_64-linux-gnu/valgrind/memcheck-amd64-linux)
    ==296==    by 0x5803DE9A: ??? (in /usr/lib/x86_64-linux-gnu/valgrind/memcheck-amd64-linux)
    ==296==    by 0x5803CD9F: ??? (in /usr/lib/x86_64-linux-gnu/valgrind/memcheck-amd64-linux)
    ==296==    by 0x58041F04: ??? (in /usr/lib/x86_64-linux-gnu/valgrind/memcheck-amd64-linux)
    ==296==    by 0x5803C1D8: ??? (in /usr/lib/x86_64-linux-gnu/valgrind/memcheck-amd64-linux)
    ==296==    by 0x58017AF4: ??? (in /usr/lib/x86_64-linux-gnu/valgrind/memcheck-amd64-linux)
    ==296==    by 0x1002D6BFB2: ???
    ==296==    by 0x1002CA9F2F: ???
    ==296==    by 0x1002CA9F17: ???
    ==296==    by 0x1002CA9F2F: ???
    ==296==    by 0x1002CA9F3F: ???
    
    sched status:
      running_tid=1
    
    Thread 1: status = VgTs_Runnable (lwpid 296)
    ==296==    at 0x10993E: setFeld (in /mnt/c/Users/Swordfish/a.out)
    ==296==    by 0x109C04: main (in /mnt/c/Users/Swordfish/a.out)
    client stack range: [0x1FFEFFE000 0x1FFF000FFF] client SP: 0x1FFF000030
    valgrind stack range: [0x1002BAA000 0x1002CA9FFF] top usage: 9480 of 1048576
    


  • Wenn Du sowas machst wie:

    int *foo = malloc(ROWS * sizeof(int*));
    

    hast Du einen zusammenhängenden Speicherbereich für ROWS Zeiger auf int.
    foo[0] ist der erste dieser Zeiger, foo[ROWS - 1] ist der letzte.

    Dann alloziierst Du mit malloc() die "zweite Dimension" und lässt diese Zeiger foo[0 ... ROWS-1] darauf zeigen:

    for (size_t row = 0; row < ROWS; ++row)
        foo[row] = malloc(COLUMNS * sizeof(int));
    

    Darauf zugreifen kannst Du nun mit foo[row][column].
    Was Du aber nicht machen kannst ist den ersten Zeiger aus foo (foo[0]) nehmen und darauf lustig hinzuaddieren. Die einzelnen Speicherbereiche auf die die Zeiger foo[0 ... ROWS-1] zeigen HÄNGEN NICHT ZUSAMMEN!



  • @Swordfish
    Mit

    int **feld = malloc(width * sizeof(int));
    for(cnt=0; cnt<width; cnt++) feld[cnt]=malloc(height * sizeof(int));
    

    alloziiere ich doch ein Feld von Zeigern das auf int-typen zeigt?
    wenn ich

    *feld = malloc(width * sizeof(int *));
    

    asführe warnt mich der Compiler mit
    warning: assignment to ‘int’ from ‘void *’ makes integer from pointer without a cast [-Wint-conversion]
    174 | *feld = malloc(width * sizeof(int *));
    wenn ich

    *feld = (int)malloc(width * sizeof(int *));
    

    ausführe mit warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
    174 | *feld = (int)malloc(width * sizeof(int *));

    Ich denke die Breite der Typen kann auf unterschiedlichen Platformen zu Problemen führen?
    Auch kann ich dann mit

    &feld[0][0]
    

    nicht mehr die Adresse an eine Funktion übergeben



  • T'schuldige, das da:

    @Swordfish sagte in Untypischer Laufzeitfehler durch malloc():

    Wenn Du sowas machst wie:

    int *foo = malloc(ROWS * sizeof(int*));
    

    sollte natürlich

    int **foo = malloc(ROWS * sizeof(int*));
    //   ^
    

    heißen.



  • @EL-europ sagte in Untypischer Laufzeitfehler durch malloc():

    alloziiere ich doch ein Feld von Zeigern das auf int-typen zeigt?

    Ja, damit bekommst Du ein "Array" von Zeigern auf int.
    feld zeigt dann auf einen zusammenhängenden Speicherbereich für diese Zeiger.

    Dann alloziierst Du für jeden dieser Zeiger ein "Array" von ints. Diese einzelnen Bereiche sind auch jeweils zusammenhängend, alle Werte direkt hintereinander im Speicher.

    ABER:
    Das "Array" auf das feld[1] zeigt kann ganz wo anders sein als das "Array" auf das feld[0] zeigt. Diese einzelnen "Arrays" können im Speicher überall verstreut sein.

    Deshalb kannst Du nicht einfach den ersten Zeiger feld[0] nehmen und von dem ausgehend bis feld[width * height - 1] durchgehen wie Du es zB in initalFeld() machst.



  • @Swordfish
    Ah, ok. Eben 🙂
    Um nochmal klar zu stellen:
    mit

    int **foo =malloc(cnt * sizeof(int))
    for(cnt=0; cnt<width; cnt++)feld[cnt]=malloc(height * sizeof(int));
    

    erstelle ich ein Feld in dem width*height int-typen gespeichert werden
    und mit

    feld = malloc(width * sizeof(int *));
    for(cnt=0; cnt<width; cnt++) feld[cnt]=malloc(height * sizeof(int));
    

    erstelle ich ein Feld in dem width * Zeiger auf height * int-typen zeigen? Welchen Vorteil hat das? Vielleicht Portabilität? Wenn das so ist muss ich den Zugriff auf die Zeiger und deren Werte im Programm bei Änderung auch noch über- prüfen/denken.

    Das tu jetzt mal



  • @EL-europ
    das tu ICH jetzt mal will ich sagen 🙂 sry



  • @Swordfish sagte in Untypischer Laufzeitfehler durch malloc():

    @EL-europ sagte in Untypischer Laufzeitfehler durch malloc():

    alloziiere ich doch ein Feld von Zeigern das auf int-typen zeigt?

    Ja, damit bekommst Du ein "Array" von Zeigern auf int.
    feld zeigt dann auf einen zusammenhängenden Speicherbereich für diese Zeiger.

    Dann alloziierst Du für jeden dieser Zeiger ein "Array" von ints. Diese einzelnen Bereiche sind auch jeweils zusammenhängend, alle Werte direkt hintereinander im Speicher.

    ABER:
    Das "Array" auf das feld[1] zeigt kann ganz wo anders sein als das "Array" auf das feld[0] zeigt. Diese einzelnen "Arrays" können im Speicher überall verstreut sein.

    Deshalb kannst Du nicht einfach den ersten Zeiger feld[0] nehmen und von dem ausgehend bis feld[width * height - 1] durchgehen wie Du es zB in initalFeld() machst.

    Eben hab ich dich vielleicht verstanden und was dazu gelernt?
    In beiden Fällen sind es Zeiger auf int-typen, in erster Version sind die int-arrays nicht hintereinanader im Speicher und mit

    int **feld=malloc(size * sizeof(int *));
    

    werden auch die int-arrays hintereinander im Speicher abgelegt?



  • @EL-europ sagte in Untypischer Laufzeitfehler durch malloc():

    werden auch die int-arrays hintereinander im Speicher abgelegt?

    Nein.

    Ein Doppelzeiger **feld ist kein 2D-Array - es sieht nur so aus.



  • @DirkB
    ja stimmt. Durch den wiederholten Aufruf von malloc() in der Schleife für jedes einzelne array kann nicht gewährleisten sein das sie hintereinander liegen. oder?