Programm mit Abruffunktionen,Pointern und Arrays.Seltsame Fehlermeldung

Baqk10

Mitglied
Guten Tag, ich schreibe grade ein Spielfeldprogramm.
Dabei wird das Gerüst und die Ausgabe, seperat als Unterfunktion abgerufen.
Bei der Spielfeldausgabenfunktion ist ein Fehler, vieleicht ein größerer, als ich vermute :D.
Jedenfalls ist die Fehlermeldung, dass die Infos die ich printf´n lassen will kein Array, Vektor oder Pointer sei, dabei ist es ein Array, werde ich aber im Quellcode markieren.
P.S. Im Quellcode habe ich die Gerüstfunktion weggelassen.
MfG und hier der Code:

PHP:
#include <stdio.h>
#include <stdlib.h>

#define GROESSE_FELD 4
#define DIM_ZEILE GROESSE_FELD * 2 + 1
#define DIM_SPALTE GROESSE_FELD * 2 + 1

void ausgabeSpielfeld(spielfeld,array){
    int i, j;
    for(i=0; i<(DIM_ZEILE); i++){
      for(j=0; j<(DIM_SPALTE); j++){
           printf("Spielfeld[%d][%d]\n", array[i][j]);      // Hier ist die Fehlermeldung
    }
    }
}
    int main(){
        int i;
        printf("Geben Sie die Groesse ihres Speichers an!\n");
        scanf("%d",&i);
    int array[DIM_SPALTE][DIM_ZEILE]={0};            //Zweidimensionales Array
    char **spielfeld;
    spielfeld = (char**)malloc(sizeof(char*)*(DIM_ZEILE));
        for(i=0;i<(DIM_SPALTE);i++){
            spielfeld[i] = (char*)malloc(sizeof(char)*DIM_SPALTE);
        }
        spielGeruest(**spielfeld,array);
        ausgabeSpielfeld(**spielfeld,array);
    return 0;
    }
 
Zuletzt bearbeitet:
Hi

Bei der Spielfeldausgabenfunktion ist ein Fehler, vieleicht ein größerer, als ich vermute :D.
Da vermutest du richtig - dein Funktionsprototyp ist falsch.
C:
void ausgabeSpielfeld(spielfeld,array)
//sollte sein:
void ausgabeSpielfeld(char** spielfeld, int** array)
Es ist im Übrigen keine gute Idee, zweidimensionale Arrays zu verwenden. Ein eindimensionaler Array ist einfacher zu verwalten, schneller und braucht weniger Platz. Zweidimensionale Arrays machen nur dann Sinn, wenn die einzelnen Spalten / Zeilen (sehr) unterschiedlich lang sein sollen.
Das **spielfeld ist übrigens höchstwahrscheinlich ein Fehler: Dadurch wirst du nur auf das allererste Element des ersten Arrays zugreifen können.

Und des Weiteren hast du ein nettes Memoryleak. Alles, was du mit malloc() allozierst, musst du mit free() wieder freigeben.

Gruss
cwriter
 
Hi


Da vermutest du richtig - dein Funktionsprototyp ist falsch.
C:
void ausgabeSpielfeld(spielfeld,array)
//sollte sein:
void ausgabeSpielfeld(char** spielfeld, int** array)
cwriter

Hab ich geändert, das Programm lässt sich compilieren, danke :D.
Aber nachdem ich die Größe des Speichers einlesen lasse, stürzt das Programm ab... was kann ich tun?

Wie mache ich das mit free()?Darüber habe ich noch nichts gelesen
 
Ok hab das mit free() raus, danke für den Tipp.
Aber wie bringe ich das Programm zum funktionieren?
Ich glaube das Problem liegt an der Kommunikation zwichen Unterfunktion und int main(), denn ein Teil von int main() funktioniert ja.
 
Aber nachdem ich die Größe des Speichers einlesen lasse, stürzt das Programm ab... was kann ich tun?
Z.B. herausfinden, wo das Programm abstürzt. Falls du keine IDE bzw. keinen Debugger hast, hilft meist das gute alte Printf-Debugging, du gibst also bei gewissen Schlüsselpositionen aus, wie weit das Programm es schon geschafft hat.

Übrigens: Warum schreibst du C89-Style, wenn du C99-Features benutzt? Die Variablen müssen nicht mehr immer am Beginn der Funktion stehen, sondern können auch direkt in for-Loops eingesetzt werden.

Ist dein Code oben noch aktuell? Dann würde ich mal auf den Rückgabewert von malloc() überprüfen, also Überprüfung auf NULL.

Ich nehme aber nicht an, dass dieser Code aktuell ist. Er ist sicher nicht komplett. Also zeig mal deinen ganzen Code.

Aber nachdem ich die Größe des Speichers einlesen lasse, stürzt das Programm ab... was kann ich tun?
Tust du nicht - dein i wird direkt wieder überschrieben...
(Genau genommen liest du es ein, aber du machst nichts damit)

Ich glaube das Problem liegt an der Kommunikation zwichen Unterfunktion und int main(), denn ein Teil von int main() funktioniert ja.
Und wie kommst du zu dieser Annahme?
Abschätzungen sind wichtig und gut - aber falsche Überzeugungen führen oft dazu, dass man an der falschen Stelle sucht.

Gruss
cwriter
 
Ich denke der Fehler liegt in der Unterfunktion void ausgabeSpielfeld
Also hier nun der ganze Code, mit deinen Tipps etwas korriegiert:


PHP:
#include <stdio.h>
#include <stdlib.h>

#define GROESSE_FELD 4
#define DIM_ZEILE GROESSE_FELD * 2 + 1
#define DIM_SPALTE GROESSE_FELD * 2 + 1



void spielGeruest(char **spielfeld){
    int i = 0, j = 0;
for(i = 0; i < (DIM_ZEILE); i++){
for(j = 0; j < (DIM_SPALTE); j++){
            if(!(i%2)){
                if(!(j%2)){
                    spielfeld[i][j] = '|';
                }
                else{
                    spielfeld[i][j] = '-';
                }
            }
            else{
                if(!(j%2)){
                    spielfeld[i][j] = '|';
                }
                else{
                    spielfeld[i][j] = 'x';
                }
            }
        }
    }
}
void ausgabeSpielfeld(char** spielfeld,int** array){
    int i, j;
    for(i=0; i<(DIM_ZEILE); i++){
      for(j=0; j<(DIM_SPALTE); j++){
           printf("Spielfeld[%d][%d]\n", array[i][j]);
    }
    }
}
    int main(){
        int i;
        printf("Geben Sie die Groesse ihres Speichers an!\n");
        scanf("%d",&i);
    int array[DIM_SPALTE][DIM_ZEILE]={0};            //Zweidimensionales Array
    char **spielfeld;
    spielfeld = (char**)malloc(sizeof(char*)*(DIM_ZEILE));
        for(i=0;i<(DIM_SPALTE);i++){
            spielfeld[i] = (char*)malloc(sizeof(char)*DIM_SPALTE);
        }
        free(spielfeld);
        spielGeruest(**spielfeld);
        ausgabeSpielfeld(**spielfeld,array);
    return 0;
    }
 
Also hier nun der ganze Code, mit deinen Tipps etwas korriegiert:
Ach, irgendwie wusste ich es ja.
Ok hab das mit free() raus, danke für den Tipp.
Das entspricht nicht der Wahrheit.
free() zerstört den Speicher. Du darfst niemals, unter keinen Umständen, auf einen Pointer (bzw. Speicherbereich) zugreifen, den du an free() übergeben hast (genauso wie du nie einen Heap-Pointer benutzen darfst, ohne vorher malloc() und Konsorten benutzt zu haben). Der Speicher ist nach dem free() Wasteland.
Das free() sagt, dass du den Speicher nicht mehr brauchst. Du aber gibst hier den Speicher frei und greifst dann locker-flockig weiterhin darauf zu. Das geht natürlich nicht.
Schiebe das free() direkt vor das return und zumindest der Absturz verschwindet.
Das Leak aber nicht.
Und genau darum sind zweidimensionale Strukturen zu vermeiden. Der korrekte Code wäre:
C:
for(size_t i = 0; i < DIM_ZEILE; i++) free(spielfeld[i]);
free(spielfeld);
Gerade fällt mir auf: Du machst mit dem malloc Platz für DIM_ZEILE Elemente, iterierst dann aber durch DIM_SPALTE Elemente. Sobald die beiden Werte nicht mehr gleich gross sind, hast du ein Problem.

Gruss
cwriter
 
Und wie kommst du zu dieser Annahme?
Abschätzungen sind wichtig und gut - aber falsche Überzeugungen führen oft dazu, dass man an der falschen Stelle sucht.

cwriter

Ich denke mal, da das Programm abstürzt, da es eine Berechnung nicht beenden oder ausführen kann.
Also war das Quatsch mit der Kommunikation, es muss entweder bei der dynamischen Speicherberechnung von **spielfeld oder im void spielfeldAusgabe liegen.
 
Ach, irgendwie wusste ich es ja.


Und genau darum sind zweidimensionale Strukturen zu vermeiden. Der korrekte Code wäre:
C:
for(size_t i = 0; i < DIM_ZEILE; i++) free(spielfeld[i]);
free(spielfeld);
Gerade fällt mir auf: Du machst mit dem malloc Platz für DIM_ZEILE Elemente, iterierst dann aber durch DIM_SPALTE Elemente. Sobald die beiden Werte nicht mehr gleich gross sind, hast du ein Problem.

Gruss
cwriter
So einen Code habe ich nirgendwo in meinem Programm, wo soll ich das free() hinsetzen ?
Naja aber das Feld muss wie du im Gerüst siehst ein Brett d.h. ein Quadrat sein und bei DEfine wird ja bereits definiert, das diese beiden gleich sind.
 
Ich denke mal, da das Programm abstürzt, da es eine Berechnung nicht beenden oder ausführen kann.
Sehr allgemeine Aussage. 99.999% aller Programmabstürze werden durch Speicherzugriffsfehler verursacht (wenn man Spinlocks nicht zählt, also ewig laufende Loops).
Also war das Quatsch mit der Kommunikation
Das stimmt.

es muss entweder bei der dynamischen Speicherberechnung von **spielfeld oder im void spielfeldAusgabe liegen.
Speicherberechnung? Du berechnest im Moment nichts, du verwendest Konstanten.
Es geht um die Speicherzugriffe - malloc() kann zwar fehlschlagen, aber bei einigermassen sinnvollen Grössen (< 100MB) passiert das nur, wenn dein Computer wenig RAM (übrig) hat.

So einen Code habe ich nirgendwo in meinem Programm
Eben :)

wo soll ich das free() hinsetzen ?
Wo würdest du es hinsetzen, nachdem ich dir gesagt habe, dass kein Speicherzugriff auf den Pointer nach dem free() (aber natürlich davor) und kein Zugriff vor (aber nach) malloc() sein darf?

Naja aber das Feld muss wie du im Gerüst siehst ein Brett d.h. ein Quadrat sein und bei DEfine wird ja bereits definiert, das diese beiden gleich sind.
Und jetzt bin ich mal so frech und ändere eines der Defines, da ich ein nicht-quadratisches Rechteck haben will. Du erlaubst ja 2 unterschiedliche Werte, ansonsten müsstest du ja nur eine Seitenlänge definieren.

Gruss
cwriter
 

Neue Beiträge

Zurück