Hallo Zusammen Folgendes in Visual Studio C++: unsigned int Platine_1[250][250][5]; Warum mäckert der Compiler und linker nicht, aber wenn das programm läuft es Probleme mit speicher gibt? David
Wenn das eine automatische Variable ist, reicht der Stack (Defaultgröße 1 MByte) nicht aus. Warum aber sollte das den Compiler interessieren?
Hallo Gibt es evntl. eine abhilfe? Vielleicht mit Speicherreservierung. David
Hi, so etwa müsste das funktionieren (Ausschnitt): unsigned int ***Platine_l; int i, j; // allocate memory Platine_l = (unsigned int***)malloc(250*sizeof(unsigned int**)); for(i=0; i<250; i++) { Platine_l[i] = (unsigned int**)malloc(250*sizeof(unsigned int*)); for(j=0; j<250; j++) Platine_l[i][j] = (unsigned int*)malloc(5*sizeof(unsigned int)); } // do someting // free memory for(i=0; i<250; i++) { for(j=0; j<250; j++) free(Platine_l[i][j]); free(Platine_l[i]); } free(Platine_l); Grüße mplusplus
> (unsigned int***)malloc(250*sizeof(unsigned int**));
Wenn du das Ergebnis von malloc casten musst, programmierst du
nicht C sondern C++. In diesem Fall ist new die bessere Wahl
anstellevon malloc. Noch besser wäre es allerdings dann auch
wirklich C++ zu schreiben und das ganze mit std::vector
aufzubauen.
Programmierst du allerdings wirklich in C, dann lass den Cast
weg. Er ist unnötig und kann einen grauslichen Fehler verstecken.
> Programmierst du allerdings wirklich in C, dann lass den Cast > weg. Er ist unnötig und kann einen grauslichen Fehler verstecken. Welcher Fehler kann denn da passieren? Ich habe damit noch nie ein Problem gehabt (in C). Grüße mplusplus
folgendes Szenario: Auf deinem System sei sizeof(int) != sizeof(void*) und weiters vergisst du das korrekte Header-File für malloc zu inkludieren. Damit ist das Szenario aufgesetzt. Wenn du jetzt machst int* pi = (int*)malloc( sizeof(int) ); dann passiert folgendes: Der Compiler hat keinen Prototypen für malloc (da ja das Header File nicht eingebunden wurde). Also muss der Compiler davon ausgehen, dass die Funktion malloc() einen int zurückliefert. Das muss er aufgrund der 'implizit int' Regel in C tun. Nun war eine weitere Voraussetzung, dass sizeof(int) nicht gleich sizeof(void*) sei. D.h. der Compiler nimmt vom returnierten Wert (der ja eigentlich ein Pointer ist) eine falsche Bytezahl her. Da du einen cast da drinnen hast, wird diese falsche Bytezahl in einen Pointer konvertiert und zugewiesen. Im Endeffekt erhält die Pointervariable nicht die Adresse die malloc zurückliefert, weil diese zwischendurch mal auf einen int umgewandelt wurde. Der Compiler wird dazu auch nichts weiter sagen, da ihn der cast ruhigstellt. Immer dran denken: Ein cast ist die C-Schreibweise für: "Lieber Compiler. Mir ist scheissegal ob du denkst dass die Datentypen nicht passen. Ich bin der Programmierer und ich habe das sagen und du tust gefälligst was ich dir sage, egal was die C-Regeln sagen". Und das tut der Compiler. Lässt du allerdings den cast weg, dann gibst du dem Compiler die Möglichkeit dich auf den Fehler aufmerksam zu machen. Den ein int kann nicht an einen Pointer zugewiesen werden. Der Compiler wird also meckern. Du überlegst wie das sein kann, denn immerhin liefert malloc einen Pointer und du weist den an eine Pointer- Variable zu. Wie kommt der Compiler also dazu, von einer int Zuweisung an einen Pointer zu faseln. Und die Antwort ist: malloc.h wurde nicht inkludiert und daher gelten Standardannahmen die besagen, dass alles was nicht bekannt ist, in desem Fall der Returntyp von malloc(), als int anzunehmen ist. Und daher ist es in C besser, diesen cast nicht zu schreiben. Generell ist es immer besser, einen cast der nicht gebraucht wird auch nicht zu schreiben. Aus dem einfachen Grund weil ein cast effektiv die Typ-Überprüfung des Compilers ausschaltet. "Lieber Compiler. Mir ist ..."
> Im Endeffekt erhält > die Pointervariable nicht die Adresse die malloc zurückliefert, > weil diese zwischendurch mal auf einen int umgewandelt wurde. Konkret könnte das zb so aussehen: sizeof( void* ) == 8 sizeof( int ) == 4 malloc() legt als Returnwert 8 Bytes auf den Returnstack für die Adresse. Der Aufrufer holt sich aber nur 4 davon. Nicht nur, dass damit die zurückgegebene Adresse verstümmelt wird, kommt auch der Returnstack komplett durcheinander.
Einfacher, wenn auch nicht eleganter, wäre die Vergrößerung des verwendeten Stacks. Das geht mit der VC-Linkeroption /STACK:nnnn (nnn ist die Größe in Bytes). In VC++ 6.0 gibt es dazu sogar ein GUI: Project Settings->Linker->Output->Stack Allocations "Reserve" Alternativ könnte die Variable auch als "static" oder als globale Variable deklariert werden. Eleganter ist allerdings keine dieser Vorgehensweisen.
Vielen Dank für diese ausführliche Beschreibung. Die 'implizit int' Regel war mir unbekannt. Man lernt nie aus... Grüße mplusplus
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.