Zur Übersicht - INFO - Neueste 50 Beiträge - Neuer Beitrag - Suchen - FAQ - Zum CC1-Forum - Zum CC-Pro-Forum

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
Ich nutze:
C-Control II Unit, C164CI-ControllerBoard, CC2-Application-Board, CC2-StarterBoard, CC2-ReglerBoard, OSOPT V3.0, OSOPT V3.1
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: