mikrocontroller.net

Forum: PC-Programmierung 3-D Zahlenfelder und Probleme


Autor: Dave_ (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn das eine automatische Variable ist, reicht der Stack (Defaultgröße
1 MByte) nicht aus.

Warum aber sollte das den Compiler interessieren?

Autor: Dave_ (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Gibt es evntl. eine abhilfe? Vielleicht mit Speicherreservierung.

David

Autor: mplusplus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> (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.

Autor: mplusplus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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 ..."

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: mplusplus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für diese ausführliche Beschreibung. Die 'implizit int'
Regel war mir unbekannt. Man lernt nie aus...

Grüße

mplusplus

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.