Schutzverletzung bei Matrix
-
Hallo,
ich habe ein kleines Problem mit einer Schutzverletzung. Habe gerade verschiedene Dinge mit Matrizen ausprobiert und immer wieder eine Segmentation fault in der Ausgabe gehabt.
Da es bei verschiedenen Operationen auftritt, denke ich, dass ich einen generellen (Denk?)-Fehler drin habe.
Bei folgender einfacher Operation tritt die Schutzverletzung bei allen Werten für s und z > 3 auf.
#include <stdio.h> #include <stdlib.h> int fill(int z, int s, int mat[z][s]){ int i, j; for(i=0;i<z;i++){ for(j=0;j<s;j++) mat[i][j]=rand()%2; } } int output(int z, int s, int mat[z][s]){ int i,j; for(i=0;i<z;i++){ for(j=0;j<s;j++) printf("%i ", mat[i][j]); printf("\n"); } } int main(){ int z, s; int matrix[z][s]; z=4; s=4; fill(z,s,matrix); output(z,s,matrix); }
Bin Anfänger (wie man sieht) und echt ratlos.
Vielen Dank für eure Hilfe!
-
int main(){ int z, s; int matrix[z][s];//woher soll die matrix hier wissen, wie groß sie sein soll? z=4; s=4; fill(z,s,matrix); output(z,s,matrix); }
-
Du verwendest hier ein C99 Feature namens variable length Arrays. Das Problem ist, dass z und s zum Zeitpunkt da die Größe der Matrix bestimmt wird einen undefinierten Wert haben. Du musst z und s natürlich festlegen bevor du sie in der Definition der Matrix verwendest. Da z und s hier aber offenbar sowieso nicht variabel sein müssen, würde ich empfehlen, die Werte const zu machen, wodurch der dann Code auch mit nicht C99 fähigen Compilern kompatibel ist...
-
In Zeile 26 hast du ein Array mit einer undefinierten Größe.
Ich wage auch mal einen Schuss ins Blaue: Du willst gar keine VLAs (variable length arrays) benutzen, sondern hast dieses selten genutzte (und eher verpönte) Sprachfeature bloß versehentlich genutzt. Liege ich mit dieser Vermutung richtig? Falls ja: Lies dir ganz dringend noch einmal die Grundlagen zur Behandlung von Arrays (ohne variable Länge) durch, insbesondere wie man sie an Funktionen übergibt. Denn der gezeigte Code wäre für normale Arrays falsch.
edit: Siehe oben. Ich tippe bloß zu langsam.
-
Zuerst einmal danke für die schnellen Antworten!
@Sepp: Du hast mit deiner Vermutung natürlich Recht und dot hat mir Kenntnisse unterstellt, die ich gar nicht habe.
Mit konstanter Zeilen- und Spaltengröße hätte ich es folgendermaßen gemacht (scheint auch zu funktionieren):
#include <stdio.h> #include <stdlib.h> #define z 4 #define s 6 int fill(int mat[z][s]){ int i, j; for(i=0;i<z;i++){ for(j=0;j<s;j++) mat[i][j]=rand()%2; } } int output(int mat[z][s]){ int i,j; for(i=0;i<z;i++){ for(j=0;j<s;j++) printf("%i ", mat[i][j]); printf("\n"); } } int main(){ int matrix[z][s]; fill(matrix); output(matrix); }
Ist daran irgendwas auszusetzen? Irgendwas falsch übergeben?
Und wenn ich die Spalten- und Zeilenanzahl variabel halten will bzw. vom Nutzer eingeben lassen möchte, könnte ich es dann einfach so machen (auch das scheint zu funktionieren)?
int main(){ int z; int s; printf("\nBitte Anzahl der Zeilen angeben: "); scanf("%i", &z); printf("\nBitte Anzahl der Spalten angeben: "); scanf("%i", &s); int matrix[z][s]; fill(z, s, matrix); output(z, s, matrix); }
-
Guiri schrieb:
#define z 4 #define s 6
Dir ist schon klar, das
jedes
einzelne z bzw s durch die Zahlen ersetzt werden?Darum nimmt man i.A. für defines Großbuchstaben und natürlich aussagekräftiger Namen.
#define MATRIX_ANZ_ZEILEN 4 #define MATRIX_ANZ_SPALTEN 6
-
Oder noch besser: Man nimmt gar kein #define, sondern const, am besten so lokal wie möglich...
int main() { const int z = 4; const int s = 6; ... }
-
dot schrieb:
Oder noch besser: Man nimmt gar kein #define, sondern const, am besten so lokal wie möglich...
int main() { const int z = 4; const int s = 6; ... }
das kompiliert aber kein c89 compiler
-
edit:
-
...
-
DirkB schrieb:
Guiri schrieb:
#define z 4 #define s 6
Dir ist schon klar, das
jedes
einzelne z bzw s durch die Zahlen ersetzt werden?Darum nimmt man i.A. für defines Großbuchstaben und natürlich aussagekräftiger Namen.
#define MATRIX_ANZ_ZEILEN 4 #define MATRIX_ANZ_SPALTEN 6
Prinzipiell ist mir schon klar, was das "define" bewirkt. Mir ist aber durch dein Posting gerade noch einmal klar geworden, welchen Sinn die Großbuchstaben und die konkretere Parameterbenennung hat.
Und ansonsten: Danke an alle!
-
a-a schrieb:
dot schrieb:
Oder noch besser: Man nimmt gar kein #define, sondern const, am besten so lokal wie möglich...
int main() { const int z = 4; const int s = 6; ... }
das kompiliert aber kein c89 compiler
Nun, ich hab das natürlich mit drei verschiedenen Compilern (MSVC, gcc und Comeau) getestet und alle haben es anstandslos kompiliert. Aber ich kann im C90 Standard tatsächlich nichts finden, das das erlauben würde. Wieder was gelernt...
-
dot schrieb:
Nun, ich hab das natürlich mit drei verschiedenen Compilern (MSVC, gcc und Comeau) getestet und alle haben es anstandslos kompiliert. Aber ich kann im C90 Standard tatsächlich nichts finden, das das erlauben würde. Wieder was gelernt...
natürlich ... tja ... dann teste noch einmal
zu den anderen beiden compiler kann ich nix sagen, aaaber was msvc betrifft:
das wirst wohl im c++ modus getestet haben, denn sonst würdest du nenerror C2057: Konstanter Ausdruck erwartet
bekommen :p
das ergibt jedenfalls mein test mit dem mvsc 2012
-
Oh verdammt, ich hab natürlich im C Modus getestet, aber mir dämmert grad, dass ich wohl überall einfach den Code aus meinem Beispiel reinkopiert hab, der gar kein Array enthält *facepalm*
Danke für den Hinweis und wie gesagt, laut C Standard so oder so tatsächlich nicht erlaubt...leider...