Klassenfrage :)



  • @EL-europ Es "funktioniert" gar nicht. Du kopierst paras.xres*paras.yres*sizeof(int) Bytes von thr_matrix[0][0] beginnend nach matrix[0][0].
    Wenn dir der Speicher gehört, wird das kopiert was da drinnen steht. Wenn dir der Speicher nicht gehört, macht vermutlich dein Programm nen Abflug.

    In dem Code der im Github ist gibt es an der Stelle keinen std::vector, das ist ein int **matrix; siehe (https://github.com/momefilo/mandelbrodt/blob/main/include/_Apple.h)



  • @Schlangenmensch
    ich muss wohl warten bis ich mir ein neues Buch Kaufe und die Ganze Thread-Funktion im sauberem c++ hinzubekommen. so das dort die c-arrays überflüssig werden. Denn wenn ich darüber iterieren muss um zu kopieren geht mir der Vorteil durch die threads zum Teil zumindest wieder verloren



  • @Schlangenmensch
    Ja genau die matrix hab ich ja deswegen als solches definiert, also wo soll da das Problem sein?
    Das ist kein Lehrbuchcode aber er läuft auf meinem Raspi5, nach dem beheben des groben Schnitzers, bei mir einwandfrei

    Bin grad wieder am Funktionen hizufügen weil ich sonst nichts mit dem Code machen kann ohne neues Buch. Und die Funktionen sind einfach ohne Threads, dazu reicht mir Internet



  • @EL-europ sagte in Klassenfrage 🙂:

    Ah mom das Funktioniert also nur weil er zufällig zusammenhängenden Speicher alloziert? Oder wo ist das prop?

    Führe doch mal das Beispiel aus! Ist nicht schwer und beisst dich nicht! Aber der Erkenntnisgewinn wird groß werden!



  • @EL-europ sagte in Klassenfrage 🙂:

    Das ist kein Lehrbuchcode aber er läuft auf meinem Raspi5, nach dem beheben des groben Schnitzers, bei mir einwandfrei

    Kennst du nicht den Programmieren-Witz: "Es kompiliert (bzw. funktioniert) bei mir, ich kann ausliefern"?

    Welchen groben Schnitzer meinst du jetzt?



  • @Th69
    Das Freigeben des zu vor allozierten speichers um wieder neuen unter der selben Variable zu allozieren, in Apple->calc() für die lokalen rohen c-arrays



  • @Quiche-Lorraine
    Führe doch mal das Beispiel aus! Ist nicht schwer und beisst dich nicht! Aber der Erkenntnisgewinn wird groß werden!
    er kopiert den inhalt beginnend der start adressen
    Es sind ja beides rohe c-arrays



  • @EL-europ sagte in Klassenfrage 🙂:

    er kopiert den inhalt beginnend der start adressen
    Es sind ja beides rohe c-arrays

    Ok, du möchtest keine Hilfe.

    Und Tschüss..



  • @EL-europ
    Es kann zufällig funktionieren. Es kann blödsinn ausgeben. Es kann abstürzen. Der Code ist einfach inhaltlich falsch, auch wenn es kompiliert und ausgeführt wird.

        int** matrix = (int**)malloc(xres * sizeof(int*));
        for (int i = 0; i < xres; i++)
          matrix[i] = (int*)malloc(yres * sizeof(int));
        int Count = 0;
    
        for (int x = 0; x < xres; x++)
        {
          for (int y = 0; y < yres; y++)
          {
            matrix[x][y] = Count++;
          }
        }
    
        int** matrix2 = (int**)malloc(xres * sizeof(int*));
        for (int i = 0; i < xres; i++)
          matrix2[i] = (int*)malloc(yres * sizeof(int));
    
        memcpy(matrix2, matrix, xres * yres * sizeof(int));
        //int* P = *matrix;
    
        for (int x = 0; x < xres; x++)
        {
          for (int y = 0; y < yres; y++)
          {
            printf("%i ", matrix2[x][y]);
          }
          printf("\n");
    
        }
        free(matrix);
        free(matrix2);
    

    Führe das 10 mal aus. Kann gut gehen, muss aber nicht.

    int main() {
      int xres = 5;
      int yres = 5;
     
    
      for (int z = 0; z < 10; ++z)
      {
        int** matrix = (int**)malloc(xres * sizeof(int*));
        for (int i = 0; i < xres; i++)
          matrix[i] = (int*)malloc(yres * sizeof(int));
        int Count = 0;
    
        for (int x = 0; x < xres; x++)
        {
          for (int y = 0; y < yres; y++)
          {
            matrix[x][y] = Count++;
          }
        }
    
    
    
        int** matrix2 = (int**)malloc(xres * sizeof(int*));
        for (int i = 0; i < xres; i++)
          matrix2[i] = (int*)malloc(yres * sizeof(int));
    
        memcpy(matrix2, matrix, xres * yres * sizeof(int));
        //int* P = *matrix;
    
        for (int x = 0; x < xres; x++)
        {
          for (int y = 0; y < yres; y++)
          {
            printf("%i ", matrix2[x][y]);
          }
          printf("\n");
    
        }
    
        free(matrix);
        free(matrix2);
      }
      return 0;
    }
    

    Schleife drum rum, und noch keinen Durchlauf hinbekommen bei dem das passiert wäre, was du hoffst.



  • @EL-europ: Abschließend von mir noch ein paar Hinweise.
    Nur die Freigabe von matrix reicht auch nicht aus, denn du hast ja mehrfache malloc-Aufrufe (eben explizit für jeden matrix[i]), so daß du auch diese freigeben mußt (zu jedem malloc-Aufruf gehört ein zugehöriges free).
    Du kannst dir auch mal diese Werte (matrix, matrix[i]) ausgeben lassen.
    Vielleicht bringt dich das auf die wichtige Erkenntnis.

    Und am besten ist es auch, du erzeugst dir viele einzelne Testprogramme (gerade um C++ auch zu verstehen) bzw. nutzt ein Test-Framework (wie z.B. Google Test). Diese kannst du auch dann auf deinem Entwicklungssystem ausführen (anstatt auf dem RASPI).
    Dann wirst du auch erkennen, daß du dein Programm anders strukturieren solltest - auch damit du Fehler selber besser und schneller identifizieren kannst.

    Edit:
    Hier noch der Link zu einer 2D-Array Klasse für C++: Array2D: Evolution von manueller Speicherverwaltung zur STL



  • @Schlangenmensch

    int main(){
        int xres=10;
        int yres=10;
        for(int count=0; count<1000; count++){
    		int **thr_matrix = (int**)malloc(xres * sizeof(int*));
    		for(int i=0; i<xres; i++){
    			thr_matrix[i] = (int*)malloc(yres * sizeof(int));
    		}
    		int **matrix = (int**)malloc(xres * sizeof(int*));
    		for(int i=0; i<xres; i++){
    			matrix[i] = (int*)malloc(yres * sizeof(int));
    		}
    		int z = 0;
    		for(int x=0; x<xres; x++){
    			for(int y=0; y<yres; y++){
    				thr_matrix[x][y] = z++;
    			}
    		}
    		memcpy(matrix, thr_matrix, (xres*yres)*sizeof(int));
    		for(int x=0; x<xres; x++){
    			for(int y=0; y<yres; y++){
    				if(matrix[x][y] != thr_matrix[x][y]){
    					printf("matrix[x][y]=%d, thr_matrix[x][y]=%d\n", matrix[x][y], thr_matrix[x][y]);
    					printf("count %d\n", count);
    				}
    			}
    		}
    		free(matrix);
    		free(thr_matrix);
    	}
    }
    

    Beim compilieren meckert er:
    test.cpp: In function ‘int main()’:
    test.cpp:38:23: warning: ‘void* memcpy(void*, const void*, size_t)’ writing 400 bytes into a region of size 80 overflows the destination [-Wstringop-overflow=]
    38 | memcpy(matrix, thr_matrix, (xres*yres)*sizeof(int));
    | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    test.cpp:28:45: note: destination object of size 80 allocated by ‘malloc’
    28 | int matrix = (int)malloc(xres * sizeof(int*));

    Da hat der Compiler doch vergessen das ich noch yres-mal thr_matrix[i] alloziiert habe? oder?

    Bei mir macht das prog hier keine Ausgabe, also alles ok?



  • @EL-europ sagte in Klassenfrage 🙂:

    Da hat der Compiler doch vergessen das ich noch yres-mal thr_matrix[i] alloziiert habe? oder?

    Sorry, aber was ist wohl wahrscheinlicher:
    a) du hast den Code nicht verstanden
    b) der Compiler hat etwas vergessen (und noch dazu in einem Beispiel, das extra für dich für dein Verständnisproblem erstellt wurde)

    Bei mir macht das prog hier keine Ausgabe, also alles ok?

    Im Programm von @Schlangenmensch ist ein printf drin. Wenn dann keine Ausgabe kommt, ist alles ok? Da die Datei bei dir test.cpp heißt: du führst nicht zufällig das shell-builtin test aus?



  • @wob
    Lies den Code!



  • Gebe mal vor und nach dem memcpy die Werte (Adressen) von matrix[i] und thr_matrix[i] aus!

    Und hier noch eine Erklärung zu Multidimensionale Arrays in C (lies besonders "3 Multidimensionale Arrays" - beachte den Unterschied zwischen den beiden Arrays!).

    Selbst mit (dem nicht mehr zu einer Warnung führenden)

    memcpy(matrix, thr_matrix, xres * sizeof(int*)); // gleiche Angabe wie beim malloc!!!
    

    werden hier nur die Zeiger kopiert, d.h. mit matrix[x][y] != thr_matrix[x][y] greifst du zweimal auf denselben Speicherbereich zu (d.h. es kann also niemals zu einem Ungleich kommen)!!!

    PS:

    @EL-europ sagte in Klassenfrage : ):
    Da hat der Compiler doch vergessen das ich noch yres-mal thr_matrix[i] alloziiert habe? oder?

    Das weiß der Compiler aber nicht, denn die Allokation findet ja erst zur Laufzeit statt!



  • Ich habe mal was dazu geschrieben: 2D Array in C++



  • @EL-europ Dir erklären hier verschiedene Experten, dass dein Kopieren so nicht geht und trotzdem beharrst du dadrauf, das das kein Problem sei.

    Du musst deine Matrix zeilenweise kopieren, sonst wird das nix.

    irgendwie sowas

        for (int x = 0; x < xres; x++) {
          memcpy(matrix[x], thr_matrix[x], yres * sizeof(int));
        }
    

    Aber, es geht ja um C++, da macht man das alles nicht:

    int main() {
      int xres = 10;
      int yres = 10;
      for (int count = 0; count < 1000; count++) {
        std::vector<std::vector<int>> thr_matrix(xres);
        for(auto& v : thr_matrix)
        {
          v.resize(yres);
        }
    
        int z = 0;
        for (int x = 0; x < xres; x++) {
          for (int y = 0; y < yres; y++) {
            thr_matrix[x][y] = z++;
          }
        }
        auto matrix = thr_matrix;
        for (int x = 0; x < xres; x++) {
          for (int y = 0; y < yres; y++) {
            if (matrix[x][y] != thr_matrix[x][y]) {
              printf("matrix[x][y]=%d, thr_matrix[x][y]=%d\n", matrix[x][y], thr_matrix[x][y]);
              printf("count %d\n", count);
            }
          }
        }
      }
    }
    

    Ist viel einfacher, man kann viel weniger Fehler machen und es gibt auch keine Performance Probleme. Noch schöner wird es, wenn man den Artikel von @DocShoe berücksichtigt und 2 D richtig macht.



  • @Th69
    Der speicher wird ja aber erst wieder vor einer neuberechnung, wenn die Werte nicht mehr gebraucht werden, freigegeben; zuvor bleibt er doch erhalten? so das die Zeiger auf die richtigen Werte zeigen



  • Nein! Mit dem memcpy überschreibst du die mittels

    matrix[i] = (int*)malloc(yres * sizeof(int));
    

    erstellten Werte (und bei einer, hier noch fehlenden, Freigabe würdest du dann einen Laufzeitfehler, sog. "double free", erhalten).

    @Schlangenmensch hat dir ja jetzt schon die Lösung verraten, aber eigentlich hätte schon bei deinem C -Code

    thr_matrix = matrix;
    

    vollkommen ausgereicht (denn auf das ganze Speicherallozieren und Kopieren kann man verzichten, da die Threads ja direkt den Matrix-Speicher beschreiben können - dein Code wartet ja explizit mit dem pthread_join auf die Abarbeitung aller Threads)...



  • @Th69
    ich denke mit
    matrix[i] = (int*)malloc(yres * sizeof(int));
    alloziere ich nur den speicher, und memcpy schreibt mit die neuen Zeiger in das array. Die doppelte Speicherverwaltung ist mir bewusst, das ist der Preis für Thread-Funktion



  • @Th69 sagte in Klassenfrage 🙂:

    Nein! Mit dem memcpy überschreibst du die mittels

    matrix[i] = (int*)malloc(yres * sizeof(int));
    

    erstellten Werte (und bei einer, hier noch fehlenden, Freigabe würdest du dann einen Laufzeitfehler, sog. "double free", erhalten).

    ..
    thr_matrix = matrix;

    vollkommen ausgereicht (denn auf das ganze Speicherallozieren und Kopieren kann man verzichten, da die Threads ja direkt den Matrix-Speicher beschreiben können - dein Code wartet ja explizit mit dem `pthread_join` auf die Abarbeitung aller Threads)...
    

    Das hab ich noch gar nicht ausprobiert! geht das ?