Re: warum ist meine globale variable zu groß? Kategorie: Programmierung (von André H. - 3.03.2007 21:21) | ||
Als Antwort auf warum ist meine globale variable zu groß? von Sebastian - 24.02.2007 18:14 | ||
| ||
Hallo Sebastian, Dieses Problem liegt nicht an der CC2 selbst, sondern ist ein Compiler-Fehler. Du bist scheinbar als erstes darüber gestolpert. Um einmal zu erklären, was passiert: Der Compiler besitzt eine Optimierung, um Berechnungen konstanter Ausdrücke bereits beim Kompilieren auszuführen. Aus x= a+(5-2)*3; wird folgendes kompiliert: x= a+9; Hierbei wird auch das überschreiten des Wertebereichs eines Datentyps berücksichtigt. (z.B. Integer zu Long) Nun mu� man ein paar Dinge zu eigenen Datentypen wissen, um zu verstehen, was diese Optimierung mit eigenen Datentypen zu tun hat. Eigene Datentypen werden intern als einfache Datenarrays behandelt. Der Index wird in Deinem Fall aus den drei Parametern und anhand der Grö�e jeder Elementdimension berechnet. In Deinem Fall hat dieses Array 40320 Byte. Und genau hier liegt der Knackpunkt. Greift man nun auf mittels konstanter Parameter, hier test.x[60].y[15].z[4].a , zu, dann versucht der Compiler diese drei Zahlen schon wärend dem Kompilieren zu berechnen und einen konstanten Ausdruck daraus zu erstellen. Und hier kommen wir bereits zum Problem. Das (Byte-)Index auf diese Variable ist über 32767, und somit au�erhalb des Integerbereichs. Der Index ist nämlich 39032. Hier wechselt der Compiler den Wertbereich auf Longinteger. Longinteger-Konstanten werden nicht wie Byte-und Integer-Konstanten im VM-Code eingebettet, sondern im Konstantenspeicher abgelegt. Und genau bei der Abfrage dieser Konstante passiert beim Kompilieren ein Fehler: thread main { test.x[60].y[15].z[4].a = 1; } 324 : VM_LOAD_IMMEDIATE_BYTE 1 134 20 : VM_LOAD_IMMEDIATE_INT 20 68 : VM_LOAD_IMMEDIATE_BYTE 0 69 : VM_ADD CALC_INT_INT 137 5 : VM_LOAD_CONST_LONG 5 325 : VM_ADD CALC_INT_LONG 68 : VM_LOAD_IMMEDIATE_BYTE 0 837 : VM_ADD CALC_LONG_INT 134 600 : VM_LOAD_IMMEDIATE_INT 60 837 : VM_ADD CALC_LONG_INT 68 : VM_LOAD_IMMEDIATE_BYTE 0 837 : VM_ADD CALC_LONG_INT 8260 : VM_LOAD_IMMEDIATE_BYTE 20 837 : VM_ADD CALC_LONG_INT 68 : VM_LOAD_IMMEDIATE_BYTE 0 837 : VM_ADD CALC_LONG_INT 21 : VM_STORE_REF_INT 132 65514 : VM_BRANCH -22 65535 65535 65535 65535 65535 65535 65535 65535 65535 65535 Im Stack steht ein Long-Wert(32-Bit). Der VM-Code VM_STORE_REF_INT erwartet aber einen 16Bit-Wert im Stack. Und genau hier passiert ein Neustart, da das OS völlig korrekt dies als Fehler ansieht und das Programm neu startet. Das ist eine Sicherheitsma�nahme im OS, bevor die CC2 infolge eines Fehlers im Kompilat verrücktspielen kann. Allerdings kenne ich keine Anwendung, bei der dieses Problem wirklich ein Problem ist. Denn, man greift auf Arrays, besonders auf eigene Datentypen, normalerweise nicht mit Konstanten Ausdrücken zu, sondern mit Variablen. Denn dann tritt dieses Problem nicht auf. Gibt man z.B. für die oberste Ebene Deines Datentyps eine Variable, und keine Konstante an, besteht das Problem nicht mehr, da der Wertebereich Integer bleibt: byte i; thread main { i=60; test.x[i].y[15].z[4].a = 1; } 15428 : VM_LOAD_IMMEDIATE_BYTE 60 147 40340 : VM_STORE_BYTE 40340 324 : VM_LOAD_IMMEDIATE_BYTE 1 134 20 : VM_LOAD_IMMEDIATE_INT 20 68 : VM_LOAD_IMMEDIATE_BYTE 0 69 : VM_ADD CALC_INT_INT 139 40340 : VM_LOAD_BYTE 40340 134 640 : VM_LOAD_IMMEDIATE_INT 640 71 : VM_MUL 69 : VM_ADD CALC_INT_INT 68 : VM_LOAD_IMMEDIATE_BYTE 0 69 : VM_ADD CALC_INT_INT 134 600 : VM_LOAD_IMMEDIATE_INT 600 69 : VM_ADD CALC_INT_INT 68 : VM_LOAD_IMMEDIATE_BYTE 0 69 : VM_ADD CALC_INT_INT 8260 : VM_LOAD_IMMEDIATE_BYTE 0 69 : VM_ADD CALC_INT_INT 68 : VM_LOAD_IMMEDIATE_BYTE 0 69 : VM_ADD CALC_INT_INT 21 : VM_STORE_REF_INT 132 65508 : VM_BRANCH -28 65535 65535 65535 65535 Der Compiler optimiert zwar noch die 15 und die 4 zu einem Offset von 600, aber der Rest wird zur Laufzeit berechnet. (60*640) Ich glaube, so sollte es klar sein, was hier passiert. Noch eine Anmerkung zur Setzung von Klammern: Ich wei�, da� es in C üblich ist, die geschweiften Klammern so zu plazieren, wie Du es machst, jedoch ist es extrem unübersichtlich. Besser ist es, die Klammern immer in dieselbe Ebene zu setzen: thread xy { loop { if <Bedingung> { //... } else { //... } while <Bedingung> { //... } } } Auf diese Weise können auch andere den Quelltext leichter lesen. MfG André H. > Hi, > > ich benutze folgende datenstruktur: > > > type t4{ > int a; > int b; > int c; > int d; > } > type t3{ t4 z[5]; } > type t2{ t3 y[16];} > type t1{ t2 x[63];} > > > sie belegt 40320 byte. (63*16*5*4*2) > das sagt auch die c2p.vmc: > > > CC2VMC > 64 > 240 > > 1 0 0 0 148 157 148 157 > > > ich habe 128kb für das programm, es sollte also genug platz sein. > Wenn ich aber in den oberen bereich (ab etwa t2[55]) daten ungleich 0 schreibe, spielt die CC2 verrückt. > > woran liegt das? > > hier ein komplettes programm zum testen: > bei mir ist dauernd der piezo zu hören, denke die cc2 bootet dauernd neu ... > > > type t4{ > > int a; > int b; > int c; > int d; > > } > > type t3{ > t4 z[5]; > } > > > type t2{ > t3 y[16]; > } > > type t1{ > t2 x[63]; > } > > t1 test; > > > thread main{ > > test.x[0].y[0].z[0].a = 1; > test.x[50].y[0].z[0].a = 1; > test.x[60].y[15].z[4].a = 1; > > } > > > > Antworten bitte nur ins Forum! Fragen per EMail auf Forum-Postings werden nicht beantwortet! Das macht meine Heizung gerade | ||
Antwort schreiben Antworten: |