Forum: Compiler & IDEs -554 Byte = 1 Befehl?


von Hegy (Gast)


Lesenswert?

Hallo,

ich habe gerade festgestellt, daß mein Binärcode um 554 Byte größer(!) 
wird, wenn ich einen Befehl weglasse(!) bzw. einen anderen konstanten 
Wert zuweise. Ich vermute mal, daß da die Optimierung des GCC nicht mehr 
kann, wenn der eine Befehl fehlt.

Zusammengefaßt sieht es so aus:
1
main()
2
{
3
  while(1)
4
  {
5
6
  if(...)
7
  {
8
    if(...)
9
    {
10
    }
11
    else
12
    {
13
      if(...)
14
      {
15
        switch()
16
        {
17
          // 6 case-Fälle
18
        }
19
20
        if(....)
21
        {
22
          switch(...)
23
          {
24
            // 5 case-Fälle
25
          }
26
        }
27
      }
28
    }
29
    flag_jbusmsg_ok = TRUE;
30
    DebugLed2Off;
31
  } // while(1);
32
33
  return 0;
34
}

So sieht das im groben aus.
Wenn ich flag_jbusmsg_ok (Typ uchar8) auf FALSE (=0) setzte oder den 
Befehl DebugLed2Off (= PORTA &= ~0x04) weglasse (fünft- und sechstletzte 
Zeile) oder auch beide Befehle weglasse, wird das Binärfile im Flash 
über ca. 550 Byte größer. Der Befehl "flag_jbusmsg_ok = TRUE" soll 
nämlich raus und das Proggi natürlich klein bleiben. Es würde übrigens 
von derzeit 4626 Byte auf 5180 Byte anwachsen.


Wie kann ich sowas umgehen, wenn ich den Code klein halten will?

von Frank B. (frank_b) Benutzerseite


Lesenswert?

Schau mal, wo flag_jbusmsg_ok überall verwendet wird.

Wenn es ohne diese Zeile oben nie auf true gesetzt wird, kann es gut 
sein, dass der Optimierer alle diezbezüglichen Programmteile ersatzlos 
streicht, weil es ja nie true wird...

ich meine sowas:
if (flag_jbusmsg_ok) {
 blah;
...

von Frank B. (frank_b) Benutzerseite


Lesenswert?

bzw umgekehrt :-)

von Hegy (Gast)


Lesenswert?

Es wird auf TRUE und an anderer Stelle auf FALSE gesetzt, es wird auch 
per if(...) abgefragt.
1
while(1)
2
{
3
  ...
4
  if(....)
5
  {
6
    ...
7
    if(data1 == 146)
8
    {
9
      flag_jbusmsg_ok = TRUE;
10
      ...
11
    }
12
    else
13
    {
14
      flag_jbusmsg_ok = FALSE;
15
      ...
16
    }
17
  }
18
  else
19
  {
20
    if(flag_jbusmsg_ok == TRUE)
21
    {
22
      ....
23
    }
24
  }
25
  flag_jbusmsg_ok = TRUE;
26
  DebugLed2Off;
27
}

Es ist ja nicht nur die Var., die da evtl. über wäre, das würde der GCC 
ja auch anmerkeln (warning: flag_jbusmsg_ok defined but not used), schon 
der Wert der Var., der zugewiesen wird, macht einen Riesenunterschied. 
Und auch, wenn ich den 2. Befehl darunter weglasse (DebugLed2Off), bläst 
sich das Programm auf, obwohl DebugLed2Off nur 1x verwendet wird.

Kann es war mit Sprungweite zu tun haben?

von yalu (Gast)


Lesenswert?

Schau dir den erzeugten Assembelercode an, dann wirst du wissen, wo
die 554 Bytes herkommen.

Oder poste mal ein kompilierbares Programmmodul, anhand dessen man das
Problem nachvollziehen kann.

von Hegy (Gast)


Lesenswert?

Vermutlich daher, daß eine if-Abfrage immer false ist und damit über 
ist und rausoptimiert wird. Wenn das so ist, dann wäre es hilfreich eine 
entsprechende Warnung vom GCC zu bekommen. So sucht man Fehler und 
findet sie nicht. Hätte ich eine Warnung wie bei nicht genutzten 
Variablen bekommen, würde man sich vor dem flashen schonmal nen Kopp 
machen und sich sicher sein, daß das Proggi nicht funzt.

Vermutung deswegen, weil ich die ganzen Krams mit der Variable und 
if-Abfrage komplett gekickt habe und dennoch wird der Code nicht mehr so 
klein (4626 Byte), sondern bleibt bei ca. 5100 Byte.

Meinst du wirklich jemand zieht sich den ganzen Code rein und kukkt sich 
das mal ernsthaft an?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Hegy wrote:

> Wenn das so ist, dann wäre es hilfreich eine
> entsprechende Warnung vom GCC zu bekommen.

Bekommst du auch, wenn du die entsprechenden Optionen (-Wall -Wextra)
aktivierst.  Aber wer guckt sich schon Warnungen an? ;-)

von Hegy (Gast)


Lesenswert?

Habe "mal eben schnell" nachgekukkt, was man an Optionen einstellen muß, 
damit die Warnungen über nicht erreichbaren Code kommen. Dazu muß die 
Option  -Wunreachable-code mit rein. Es wird immer eine Warnung geben in 
der main()-Fkt., weil diese ja immer mit return x; abschließt aber 
niemals aus einer while(1)-Schliefe erreicht wird.

Bzgl. meines Problems habe ich damit festgestellt, daß ein etwas 
längeres if-Statement nicht durchlaufen wird, wenn die Var. 
flag_jbusmsg_ok = TRUE ist. Wenn ich die Var. dagegen auf FALSE setze, 
besteht die Möglichkeit, daß das if-Statement durchlaufen wird und somit 
werden ca. 30 Zeilen Code mit übersetzt und nicht rausgeschmissen, was 
dann den Unterschied im Binärfile von ca. 550 Byte ausmacht. Damit wäre 
das Problem erklärt.

Also packe ich die Option -Wunreachable-code jetzt immer mit rein, hilft 
ja und Warnungen nehme ich beim GCC durchaus ernst.

von Εrnst B. (ernst)


Lesenswert?

Hegy wrote:
> ... Option  -Wunreachable-code mit rein. Es wird immer eine Warnung geben in
> der main()-Fkt., weil diese ja immer mit return x; abschließt aber
> niemals aus einer while(1)-Schliefe erreicht wird.

du kannst main mit __attribute__((noreturn)) deklarieren, wenn du da nie 
rauslaufen willst.

von Hegy (Gast)


Lesenswert?

Wie macht man sowas mit der main()-Funktion?

Ich bin wohl nicht der einzige, wo es nicht ohne Warnungen funktioniert.
http://www.mikrocontroller.net/articles/AVR-GCC-Codeoptimierung#Prolog.2FEpilog_von_main.28.29_verkleinern

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

1
int main(void) __attribute__((noreturn));
2
int
3
main(void)
4
{
5
   // ...
6
}

Wenn du einen aktuell gepatchten Compiler hast, kannst du auch mal
das Attribut OS_main ausprobieren.

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
Noch kein Account? Hier anmelden.