Forum: Compiler & IDEs Source-Code an andere Stelle -> funktioniert nicht mehr.


von Wolfgang K. (Gast)


Lesenswert?

Hallo!

Habe ein sehr komisches Problem, dass mich zur Verzweiflung bringt.

Folgenden Auszug aus dem Sourcecode für die Ansteuerung eines Pins:

if (variable_a == ON)  PORTD |= (1 << PD4);
if (variable_a == OFF)  PORTD &= ~(1 << PD4);

if (variable_b == ON)  PORTD |= (1 << PD5);
if (variable_b == OFF)  PORTD &= ~(1 << PD5);

Der Source-Code von variable_a funktioniert, der von b aber nicht.
Tausche ich nun die Zeilen untereinander aus ist es genau umgekehrt, 
variable_b funktioniert und a nicht mehr... warum?


Hier mein Memory Usage:

AVR Memory Usage:
-----------------
Device: atmega8

Program:    5144 bytes (62.8% Full)
(.text + .data + .bootloader)

Data:        125 bytes (12.2% Full)
(.data + .bss + .noinit)


Die Optimierung ist auf s gestellt.

Was ist das Problem? Compiler?

von Karl H. (kbuchegg)


Lesenswert?

Wolfgang K. wrote:

> Was ist das Problem? Compiler?

Mit 99.9% Wahrscheinlichkeit sitzt das Problem vor dem
Bildschirm :-)

Zeig mal den ganzen Code.

von Wolfgang K. (Gast)


Angehängte Dateien:

Lesenswert?

:-) Das dachte ich am Anfang auch, aber habe alles durchgesehen, da die 
Programmteile dieser Ausgänge genau gleich sind. Es ist aber alles 
komplett gleich (bis auf variablenname, usw. ;-))

Der Source-Code hat um die 900 Zeilen, darum schreibe ich noch dazu, wo 
das Problem auftritt:

Im Unterprogramm Ausgang_setzen() werden die Pins angesteuert, je 
nachdem welchen Zustand die zugehörige Variable hat. Komplett einfach 
gehalten. Der Zustand der zugehörigen Variablen in der if-Abfrage ist 
korrekt (0 oder 1), d.h. das funktioniert alles. Es funktionieren alle 
Ausgänge einwandfrei, bis auf den für den Motorraum (Zeile 478 und 479).
Tausche ich nun die beiden Zeilen für den Motorraum (Zeile 478 und 479) 
mit z.b. den Frontsystem-Zeilen (Zeile 465 und 466) aus, funktioniert 
der Motorraum-Ausgang, dafür aber ein anderer von diesen auf einmal 
nicht mehr.

Darum bin ich mir sicher, dass kein Programmfehler vorhanden ist, da der 
Ausgang, der vorher nicht funktioniert hat, auf einmal funktioniert, 
wenn man seine Code-Zeilen wo anders hinverschiebt, wo es aber keinen 
Einfluss darauf hat.


PLEASE HELP!...

von Simon K. (simon) Benutzerseite


Lesenswert?

Troll: 900 Zeilen Code in einer C-Datei... Was ist da schief gelaufen? 
;) ;)

von Wolfgang K. (Gast)


Lesenswert?

dachte am anfang das programm wird nicht so gross, hab es dann aber 
immer weiter ausgebaut und mir ist es egal, wenn alles in einer datei 
ist, und nicht auf mehrere aufgeteilt.

von Wolfgang K. (Gast)


Lesenswert?

wenn du es gekürzt haben willlst:

-) alles mit lcd funktioniert einwandfrei
-) schalter einlesen funktioniert
-) menüs funktionieren

eigentlich funktioniert ALLES einwandfrei, bis auf die Ausgabe durch die 
Variable Motorraum.
Werden die Ausgaben in einer anderen Reihenfolge getätigt, funktioniert 
eine andere nicht, aber Motorraum dafür...

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


Lesenswert?

Wolfgang K. wrote:

> dachte am anfang das programm wird nicht so gross, hab es dann aber
> immer weiter ausgebaut und mir ist es egal, wenn alles in einer datei
> ist, und nicht auf mehrere aufgeteilt.

Dir ja, aber nicht denen, die den Kram nun reviewen sollen, weil du
nicht mehr wirklich durchblickst...  Compilieren lässt es sich auch
nicht, weil noch allerlei anderer Kram ringsrum fehlt.

Aber eigentlich ist die Sache recht eindeutig:
1
        if (Fussraum == ON)             PORTD |= (1 << PD0);
2
        if (Fussraum == OFF)            PORTD &= ~(1 << PD0);
3
        if (Fussraum == BLNK)
4
        if (Fussraum == GLOW)
5
        if (Fussraum == RPM1)
6
        if (Fussraum == RPM2)
7
8
        if (Motorraum == ON)            PORTD |= (1 << PD1);
9
        if (Motorraum == OFF)           PORTD &= ~(1 << PD1);

Guck dir mal die Zeilen vor deiner ,,Problemzeile'' an, dann sollte
dir der Seifensieder aufgehen.

von Falk B. (falk)


Lesenswert?

Jörg Wunsch wrote:

> Guck dir mal die Zeilen vor deiner ,,Problemzeile'' an, dann sollte
> dir der Seifensieder aufgehen.

Hehe, böser Fehler ;-)

MFG
Falk

von Wolfgang K. (Gast)


Lesenswert?

Alles klar!!! ;-))

Hab einfach alle Zustände hingeschrieben und wollte sie nacheinander 
hinzufügen... :-))))

Danke Jörg!!!

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


Lesenswert?

Tja, mit einem Editor, der automatisch das Einrückungsniveau selbst
ermittelt, wär dir das nicht passiert...

von Marian (Gast)


Lesenswert?

Ich als Anfänger sehe das Problem immer noch nicht :). Kann mir das 
einer genau erklären oder genauer drauf zeigen?

von Falk B. (falk)


Lesenswert?

@  Marian (Gast)

>Ich als Anfänger sehe das Problem immer noch nicht :). Kann mir das
>einer genau erklären oder genauer drauf zeigen?

Ja.

1
        if (Fussraum == ON)             PORTD |= (1 << PD0);
2
        if (Fussraum == OFF)            PORTD &= ~(1 << PD0);
3
        if (Fussraum == BLNK)
4
        if (Fussraum == GLOW)
5
        if (Fussraum == RPM1)
6
        if (Fussraum == RPM2)
7
8
        if (Motorraum == ON)            PORTD |= (1 << PD1);
9
        if (Motorraum == OFF)           PORTD &= ~(1 << PD1);

Die vier if() ohne Anweiusung dahinter (welche später einfügt werden 
sollten) sind ja nicht einfach weg, sondern werden schön brav 
ausgeführt. Allerdings kommt dann eine GANZ anderes Struktur raus. 
Nämlich die (umgeschriene mit Einrückung un Klammern, verkettete If() 
Anweisungen)
1
        if (Fussraum == ON)             PORTD |= (1 << PD0);
2
        if (Fussraum == OFF)            PORTD &= ~(1 << PD0);
3
        if (Fussraum == BLNK) {
4
          if (Fussraum == GLOW) {
5
            if (Fussraum == RPM1) {
6
              if (Fussraum == RPM2) {
7
8
                if (Motorraum == ON)            PORTD |= (1 << PD1);
9
              }
10
            }
11
          }
12
        } 
13
        if (Motorraum == OFF)           PORTD &= ~(1 << PD1);

Böse Falle. Mit Pascal wär das nicht passiert ;-)

MfG
Falk

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


Lesenswert?

Wäre übrigens auch nicht passiert, wenn man das ,,Gerippe'' einfach
komplett durchgezogen hätte:
1
        if (Fussraum == ON)             PORTD |= (1 << PD0);
2
        if (Fussraum == OFF)            PORTD &= ~(1 << PD0);
3
        if (Fussraum == BLNK)           ;
4
        if (Fussraum == GLOW)           ;
5
        if (Fussraum == RPM1)           ;
6
        if (Fussraum == RPM2)           ;
7
8
        if (Motorraum == ON)            PORTD |= (1 << PD1);
9
        if (Motorraum == OFF)           PORTD &= ~(1 << PD1);

Ich vermute, dass es Wolfang auch nicht nochmal passiert. ;-)

von Simon K. (simon) Benutzerseite


Lesenswert?

Ah da drüben winkt gerade "Hr. Switch-Case" mit seinem Zaunpfahl..

von Martin T. (mthomas) (Moderator) Benutzerseite


Lesenswert?

Es schadet nicht, zumindest eine Kurzfassung der "MISRA roules" (MISRA 
Guidelines for the Use of the C Language in Vehicle Based Software) 
durchzulesen, z.B. MisraC.pdf von iar.com. Einige der Regeln sind 
vielleicht etwas übertrieben aber viele simple Fehler kann man durch 
Beachtung des Regelsatzes vermeiden. Oben wurde z.b. Rule 59 nicht 
beachtet: "The statements forming the body of an if, else if, else, 
while, do … while or for statement shall always be enclosed in braces." 
Bei Anwendung der Regel hätte man das gesehen, was Falk Brunner gezeigt 
hat und die Fehlerursache wäre deutlich offensichtlicher geworden. 
(Nähkästchen: Ja - ich beachtet die Regeln auch nicht immer wenn nicht 
grade explizit verlangt aber das hat sich auch schon gelegentlich 
gerächt und längeres "Codeanstarren" oder Debug-Sitzungen eingebracht.)

von holger (Gast)


Lesenswert?

@ Jörg

>>        if (Fussraum == BLNK)           ;

vieleicht doch besser so

        if (Fussraum == BLNK)           { }

Sonst kommt man leicht zu einem

        if (Fussraum == BLNK)           ;
         { MachMalWas(); }


Ist immer wieder nett sowas zu debuggen ;)

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


Lesenswert?

Naja, ich war schon davon ausgegangen, dass nach jedem dieser "if"s
ohnehin nur ein einfacher Ausdruck (im Sinne des ,,Bitwackelns'')
stehen soll.  Dafür finde ich wiederum, dass die Übersichtlichkeit
insgesamt am Ende besser ist, als wenn man stur der MISRA-Regel
folgt.

von holger (Gast)


Lesenswert?

Ich leg noch mal ein schönes Macro drauf ;)

#define SPI_WAIT()    while(!(SPI_STATUS_REGISTER & ( 1<<SPIF ))); 
spi_back_byte=SPI_DATA_REGISTER;


        if (Fussraum == BLNK)           SPI_WAIT();

oder doch besser ?

        if (Fussraum == BLNK)           { SPI_WAIT(); }

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


Lesenswert?

Was kann ich denn dafür, dass du wie Funktionen aussehene Makros
so schreibst, dass sie sich doch nicht wie Funktionen benehmen?

Jedes Kind :) weiß doch, dass man den Makro so schreibt:
1
#define SPI_WAIT()    do { while(!(SPI_STATUS_REGISTER & ( 1<<SPIF ))); } while (0)

(Kein Spaß.  Verquerer Konstrukt, aber der Makro tut danach, was man
von ihm erwartet.)

von holger (Gast)


Lesenswert?

>Was kann ich denn dafür, dass du wie Funktionen aussehene Makros
>so schreibst, dass sie sich doch nicht wie Funktionen benehmen?

Natürlich gar nichts.

Das hier gehört eigentlich in EINE Zeile:

>#define SPI_WAIT()    while(!(SPI_STATUS_REGISTER & ( 1<<SPIF ))); 
>spi_back_byte=SPI_DATA_REGISTER;

Das sollte nur mal verdeutlichen was einen erwarten kann
wenn man keine {} hinter if oder for setzt. Bei Macros kann
das tödlich sein.

von holger (Gast)


Lesenswert?

>>Das hier gehört eigentlich in EINE Zeile:

>>#define SPI_WAIT()    while(!(SPI_STATUS_REGISTER & ( 1<<SPIF )));
>>spi_back_byte=SPI_DATA_REGISTER;

Kleiner Nachtrag:  Das tut auch was ich möchte OHNE
diesen merkwürdigen Konstrukt. Man muss halt nur Klammern setzen.

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


Lesenswert?

holger wrote:

> Kleiner Nachtrag:  Das tut auch was ich möchte OHNE
> diesen merkwürdigen Konstrukt. Man muss halt nur Klammern setzen.

Das widerspricht aber dem `principle of least astonishment'.  Der
Implementierer des Makros (und nur der) weiß, dass sich sein Makro
nicht wirklich so verhält, wie er auf den ersten Blick aussieht
(nämlich wie eine Funktion).  Folglich sehe ich denjenigen in der
Pflicht, sich um die Vermeidung entsprechender Seiteneffekte zu
kümmern, statt diese Verpflichtung auf den Benutzer des Makros zu
übertragen (was du mit deiner zwanghaften Verpflichtung, nach einem
if ein Paar Klammern zu setzen, letztlich machst).

Klar ist der Anweder in der Regel gut beraten, wenn er die Klammern
setzt, aber da es die Sprache nicht vorschreibt, dass sie gesetzt
werden müssen, gehört es halt genauso gut zur ,,Unfallverhütung'',
dass man die Makros selbst ,,idiotensicher'' macht.  (In diese
Kategorie fällt auch mit, dass ein Makro all seine benutzten
Makro-Argumente selbst klammert.)

Alternativ kannst du deinen Makro ja auch mit einer inline-Funktion
realisieren, wenn dir der do...while(0)-Hack nicht gefällt.

von Marian (Gast)


Lesenswert?

@Falk Brunner: Danke, die 4 if Anweisungen habe ich natürlich völlig 
ignoriert :). Finde den Fehler sehr interessant, da lohnt es sich doch 
ein paar Klammern mehr zu setzen um solche Dinger ungeschehen zu machen.

von Wolfgang K. (Gast)


Lesenswert?

Dann hat mein problem schon mal jemand anderem auch geholfen... :-)

Aus fehlern lernt man und macht sie nicht mehr.

mfg

von Simon K. (simon) Benutzerseite


Lesenswert?

Jörg Wunsch wrote:
> ...
> Folglich sehe ich denjenigen in der
> Pflicht, sich um die Vermeidung entsprechender Seiteneffekte zu
> kümmern, statt diese Verpflichtung auf den Benutzer des Makros zu
> übertragen (was du mit deiner zwanghaften Verpflichtung, nach einem
> if ein Paar Klammern zu setzen, letztlich machst).
> ...

Das sehe ich genau so wie du. (Immerhin bist du hier der erfahrene 
Programmierer)

In meiner T6963c-Library habe ich auch ein paar Makros in die 
Header-Datei gepackt um zwei Funktionsaufrufe quasi zu bündeln. Dort 
habe ich ebenfalls das do{}while(0); Konstrukt benutzt.

Also: Auch wenn man weiß, dass man immer schön Klammern setzt, und genau 
deswegen das Makro schlampig designt, dann kommen die bösen Fehler 
spätestens dann, wenn nen Anfänger (oder Ahnungsloser ;)) sich den Mist 
kopiert und bei sich einbaut. Absolut Gemeingefährlich.

PS: Zum Glück hatte ich zum Zeitpunkt der T6963c Library schon was von 
dem do{}while(0);-Hack gehört. Sonst hätte ich es zu diesem Zeitpunkt 
auch nicht besser gewusst *räusper... ;)

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.