Forum: Compiler & IDEs Brauche Tipps zum Eingrenzen eines Fehlers


von Bernhard (Gast)


Lesenswert?

Ich habe das Problem, dass bei einer Übertragung die XOR Checksumme 
immer wieder falsch berechnet wird. (ca. 50 bis 70% der Checksummen 
werden falsch berechnet.)
Ich verwende einen ATtiny24.
Ich bin mir ziemlich sicher dass der Fehler bei der Berechnung passiert, 
da wenn ich die Datenquelle abhänge, wird immer die gleiche, falsche 
Checksumme überbittelt.

Dass Merkwürdige ist, dass alle Arrays Global sind, wodurch eigentlich 
keine übermäßige Ram-Menge belegt werden sollte.

Aktuell sind ca.87% des Flash, ca.53% des SRams und 0% des EE-Proms 
belegt.

Das Merkwürdige ist, dass solange ich beim Starten geladene 
Standardwerte ohne Fehler verarbeitet werden.
Der Fehler tritt erst auf, sobald das erste mal Daten eingelesen werden.
(ADC-Werte und PWM-Signale)

Vor dem Berechnen der Checksumme werden mit cli alle Interrupts 
abgedreht um mit die Daten nicht zu verändern.
Dann werden alle Daten in ein eigenes Übertragungsarray geschrieben.
Erst nach dem Kopieren der Daten werden die Interrupts wieder mit sei 
aktiviert.

Kann mir bitte jemand ein paar generelle Tipps geben wie man solche 
Fehler eingrenzen kann?
Wie kann man z.B. feststellen dass der Stack überläuft?

Bitte kommt mir jetzt nicht dass der Fehler in Programmzeile 42 liegt. 
Ich brauche nur ein paar Tipps um das Problem selbst lösen zu können.

von Floh (Gast)


Lesenswert?

Bernhard schrieb:
> Bitte kommt mir jetzt nicht dass der Fehler in Programmzeile 42 liegt.
> Ich brauche nur ein paar Tipps um das Problem selbst lösen zu können.

Was erwartest du dann hier? Mann könnte dir jetzt alles mögliche raten, 
was aber vielleicht in deinem Programm noch nicht mal verwendet wird.
Und da du noch nicht mal deine Programmiersprache explizit erwähnst, ist 
das nicht mehr Stochern im Nebel, das ist einfach Zeitverschwendung.

Aber bitte:
einfache Eingabe -> checksumme berechnen lassen -> ausgeben -> von hand 
prüfen

von Karl H. (kbuchegg)


Lesenswert?

Bernhard schrieb:

> Ich bin mir ziemlich sicher dass der Fehler bei der Berechnung passiert,

Darauf würde ich nicht wetten.
Seltsame Fehler, die völlig unerklärlich sind, haben meistens ihren 
Ursprung in einem Fehler ganz wo anders.

Arrayüberläufe, für Strings zu klein dimensionierte Arrays sind da die 
klassischen Kandidaten, allerdings sind das beileibe nicht alle 
Möglichkeiten. Eigentlich kann man erst hinterher, wenn man den Fehler 
gefunden hat, genau sagen wie sich dieser Fehler auswirkt, so dass man 
die Symptome sieht, die man sieht. Genau das ist das fiese an der Sache.

von Mark B. (markbrandis)


Lesenswert?

Folgendes kann man zum Beispiel machen:

-Auf einem normalen PC kompilieren (vorausgesetzt, die Funktion ist in C 
oder so geschrieben) und dort mal mit entsprechenden Beispielwerten 
diverse Testläufe laufen lassen. Kommt auf der anderen Plattform immer 
das richtige Ergebnis raus, kann es also nicht an der 
Prüfsummen-Funktion an sich liegen, denn man hat dann ja gezeigt dass 
sie korrekt implementiert ist.

-Debugger benutzen, Breakpoint setzen und die Funktion auf der 
Zielplattform Schritt für Schritt durchsteppen, notfalls hier mit 
Testarrays als Eingabe arbeiten weil man die Daten ja dann nicht in 
Echtzeit (über irgendeine Schnittstelle) bekommt

-Laufzeit prüfen: Einen Digitalausgang des Mikrocontrollers auf 1 setzen 
wenn die zu prüfende Funktion startet, und auf 0 setzen wenn sie endet. 
So kann man mit einem Oszilloskop sehr schön sehen, wie groß die 
Bearbeitungszeit für die Funktion ist - eventuell liegt sie nicht mehr 
im passenden Rahmen, je nachdem welchen Zeitbedingungen die Anwendung 
unterliegt.

-Generell prüfen, ob der Defekt nicht in der Hardware vorliegt: Mal den 
Mikrocontroller gegen einen anderen austauschen und die exakt gleiche 
Software aufspielen.

-Generell prüfen, ob einem nicht der (falsch eingestellte) Watchdog 
dazwischenhaut - ein beliebter Fehler, wie ich aus eigener Erfahrung in 
meinem ersten Projekt nach dem Studium erleben durfte :-)

Die Wahrscheinlichkeit, dass der Speicher an irgendeiner Stelle 
korrumpiert wird (z.B. wie von Karl heinz Buchegger beschrieben), halte 
ich für sehr viel größer als dass eine einfache Schleife über ein Array 
von Bytes und deren XOR-Verknüpfung Probleme macht.

von Bernhard (Gast)


Lesenswert?

Floh schrieb:
> Aber bitte:
>
> einfache Eingabe -> checksumme berechnen lassen -> ausgeben -> von hand
>
> prüfen
Dass war das 1. das ich gemacht habe um herauszufinden welche Seite der 
Komunikation da die falsche Checksumme liefert.

Karl heinz Buchegger schrieb:
> Bernhard schrieb:
>
>> Ich bin mir ziemlich sicher dass der Fehler bei der Berechnung passiert,
>
> Darauf würde ich nicht wetten.
> Seltsame Fehler, die völlig unerklärlich sind, haben meistens ihren
> Ursprung in einem Fehler ganz wo anders.
>
> Arrayüberläufe, für Strings zu klein dimensionierte Arrays sind da die
> klassischen Kandidaten, allerdings sind das beileibe nicht alle
> Möglichkeiten. Eigentlich kann man erst hinterher, wenn man den Fehler
> gefunden hat, genau sagen wie sich dieser Fehler auswirkt, so dass man
> die Symptome sieht, die man sieht. Genau das ist das fiese an der Sache.
Dass ist mir leider schon zu oft passiert.
Desswegen hatte ich gefragt welche Herangehensweise es gibt um den 
Fehler eingrenzen zu können. Denn jeder geht anders an die Fehlersuche 
heran. Und dadurch gibt es immer wieder nsätze an die man selbst nie im 
Leben gedacht hätte.

Arrayüberläufe kann ich (fast) ausschließen.
Denn ich habe die Felder inzwischen um 5 einträge größer germacht als 
nötug und habe auch einen Versuch mit hardcodet Zugriffen auf die Arrays 
gemacht.
(Da schreit AVR Studio wenn man außerhalb des Arrays zugreift und man 
greift nicht so schnell daneben.)
Es wird eigentlich ganz ohne Strings gearbeitet.
Ich verwende nur 8 und 16 Bit Arrays.

Was mir aufgefallen ist, ist dass AVR Studio hin und wieder ein 16 Bit 
Array dur ein 8 Bit Array ersetzt.
Und dass obwohl ich ausdrücklich unsigned short geschrieben habe.
Mir ist dass nur aufgefallen weil die Ram-Adressen der einzelnen 
Array-Werte beim Simulieren direkt aufeinander folgten.

Mark Brandis schrieb:
> Folgendes kann man zum Beispiel machen:
>
> -Auf einem normalen PC kompilieren (vorausgesetzt, die Funktion ist in C
> oder so geschrieben) und dort mal mit entsprechenden Beispielwerten
> diverse Testläufe laufen lassen. Kommt auf der anderen Plattform immer
> das richtige Ergebnis raus, kann es also nicht an der
> Prüfsummen-Funktion an sich liegen, denn man hat dann ja gezeigt dass
> sie korrekt implementiert ist.
>
> -Debugger benutzen, Breakpoint setzen und die Funktion auf der
> Zielplattform Schritt für Schritt durchsteppen, notfalls hier mit
> Testarrays als Eingabe arbeiten weil man die Daten ja dann nicht in
> Echtzeit (über irgendeine Schnittstelle) bekommt
>
> -Laufzeit prüfen: Einen Digitalausgang des Mikrocontrollers auf 1 setzen
> wenn die zu prüfende Funktion startet, und auf 0 setzen wenn sie endet.
> So kann man mit einem Oszilloskop sehr schön sehen, wie groß die
> Bearbeitungszeit für die Funktion ist - eventuell liegt sie nicht mehr
> im passenden Rahmen, je nachdem welchen Zeitbedingungen die Anwendung
> unterliegt.
>
> -Generell prüfen, ob der Defekt nicht in der Hardware vorliegt: Mal den
> Mikrocontroller gegen einen anderen austauschen und die exakt gleiche
> Software aufspielen.
>
> -Generell prüfen, ob einem nicht der (falsch eingestellte) Watchdog
> dazwischenhaut - ein beliebter Fehler, wie ich aus eigener Erfahrung in
> meinem ersten Projekt nach dem Studium erleben durfte :-)
>
> Die Wahrscheinlichkeit, dass der Speicher an irgendeiner Stelle
> korrumpiert wird (z.B. wie von Karl heinz Buchegger beschrieben), halte
> ich für sehr viel größer als dass eine einfache Schleife über ein Array
> von Bytes und deren XOR-Verknüpfung Probleme macht.

Dass habe ich auch schon gemacht.

Dass Problem ist, dass mit Daten-Tabellen und Startwerten alles richtig 
arbeitet.
Sowol auf dem PC als auch auf dem uC.
Nur sobald die richtigen Daten kommen, gibt's Fehler.
Ich vermute, dass da irgentetwas bei der Berechnung und dem Ermitteln 
der Daten nicht ganz koscher ist.
Aber da ich alle Interrupts global abdrehe, dürfte eigentlich nichts 
passieren.

Ich glaube ich werde mich dass Wochenende ausgibig mit dem Quellcode 
beschäftigen müssen.

von Karl H. (kbuchegg)


Lesenswert?

Bernhard schrieb:

>> die Symptome sieht, die man sieht. Genau das ist das fiese an der Sache.
> Dass ist mir leider schon zu oft passiert.
> Desswegen hatte ich gefragt welche Herangehensweise es gibt um den
> Fehler eingrenzen zu können.

Den Fehler gar nicht erst entstehen lassen :-)
Klingt jetzt neunmalklug, ist aber so.

In kleinen Abschnitten entwickeln. Jeden Abschnitt für sich auf Herz und 
Nieren testen.

> Denn jeder geht anders an die Fehlersuche
> heran.

Das ist gar nicht so sehr der springende Punkt.
Der springende Punkt ist, dass es unglaublich schwer ist, in ein 
fünf-tausend Zeilen Code die eine zu finden, die für das momentan 
sichtbare Symptom verantwortlich ist, wenn man nicht nachweisen kann, 
dass es 4500 nicht sein können, weil man die ausreichend getestet hat.

> Und dadurch gibt es immer wieder nsätze an die man selbst nie im
> Leben gedacht hätte.

Im Extremfall gehört auch ein Quentchen Glück mit dazu.
Debugger, die man auf Speicherzellen ansetzen kann und die sich melden, 
wenn diese Zelle ihren Wert ändert (egal warum, also Überwachung indem 
nach jeder Anweisung gecheckt wird, ob sich die Zelle verändert hat)


> Was mir aufgefallen ist, ist dass AVR Studio hin und wieder ein 16 Bit
> Array dur ein 8 Bit Array ersetzt.

Ganz sicher nicht.

>> Die Wahrscheinlichkeit, dass der Speicher an irgendeiner Stelle
>> korrumpiert wird (z.B. wie von Karl heinz Buchegger beschrieben), halte
>> ich für sehr viel größer als dass eine einfache Schleife über ein Array
>> von Bytes und deren XOR-Verknüpfung Probleme macht.
>
> Dass habe ich auch schon gemacht.
>
> Dass Problem ist, dass mit Daten-Tabellen und Startwerten alles richtig
> arbeitet.
> Sowol auf dem PC als auch auf dem uC.
> Nur sobald die richtigen Daten kommen, gibt's Fehler.

Dann bleibt dir nichts mehr anderes übrig als:
Programm mit printf (bzw dem Äquivalent) spicken und alle auch nur 
irgendwie interessant scheinenden
  * Eingangswerte
  * Zwischenwerte
  * Ergebnisse
ausgeben (UART ist da besser als LCD, weil ein Termialprogramm 
normalerweise eine längere Sitzung protokollieren kann)
Dieses Protokoll mitlesen, Werte auf Plausibilität prüfen und hoffen das 
man dort den Bereich in etwa eingrenzen kann.

Du musst die Black Box öffnen. Momentan weißt du nur, dass hinten was 
falsches raus kommt, wenn du vorne etwas reinsteckts (die Eingangswerte 
hast du hoffentlich schon geprüft. Es kommt gar nicht so selten vor, 
dass eine Funktion gar nicht die Werte vorgesetzt bekommt, die sich der 
Entwickler vorstellt und mit denen er Debugging betreibt).

Also bleibt dir nichts anderes übrig als dir ein 'Fenster' in den µC zu 
schaffen, durch welches du deinem µC möglichst gut bei der Arbeit 
zusehen kannst.

von sunburner (Gast)


Lesenswert?

Schau mal nach ob deine Arbeitsvariable zum berechnen der XOR Prüfsumme 
jedes mal zu Anfang der Berechnung richtig initialisiert wird (0 oder 
der Startwert deiner Wahl).
Oder ist einer der verwendeten Variablen mit static deklariert?
Verwendet der Compiler evtl. die Arbeitsvariable noch in einem anderen 
Zusammenhang -> volatile ?

Ohne Quellcode kann ich auch nur raten...

von Michael R. (mexman) Benutzerseite


Lesenswert?

> Ohne Quellcode kann ich auch nur raten...


Dito.

Was bei mir immer gerne passiert ;-)  :

Bei einem Rotierbefehl RLC/RRC ist vorher das Carry nicht richtig 
gesetzt....und je nach Aktivitaeten  im Interrupt kann's auch mal falsch 
sitzen ;-)



Generell stimuliert es die Motivation von Mitlesern mehr, eine sinnvolle 
Antwort zu suchen, wenn der Fragesteller mehr Informationen gibt.
Angefangen vom tollen (?) Titel "Brauche Hilfe", "Tipps gesucht", "Was 
ist der Fehler" bis zur Beschreibung der Randbedingungen:
Du schreibst nur, was nicht geht, und fragst was Du machen sollst, 
schreibst  aber nicht was Du ueberhaupt machen KANNST!
Keine Info ob ein SW-Simulator vorliegt, ob Du einen Emulator hast......

Im Simulator wuerde ich alle moeglichen Eingangswerte von 0 bis FFFF (?) 
mal stimulieren und sehen, ob Werteabhaengig was passiert,
Wenn's das nicht ist, im Emulator mal die Uebertragungen freischalten, 
aber als Werte immernoch die Defaultdaten benutzen um zu sehen, obdurch 
die Kommunikation selber etwas passiert.....



vielleicht liegt der Fehler also wirklich in Zeile 42!


gruss

Michael

von Bernhard (Gast)


Lesenswert?

Ich weis dass ich den Titel etwas unglücklich gewählt habe.
Ach etwas Quellcode schadet normalerweise nicht.

Aber es ging mir um generelle Vorgehensweisen um den Fehler 
einzugrenzen.

Karl heinz Buchegger schrieb:
> Darauf würde ich nicht wetten.
> Seltsame Fehler, die völlig unerklärlich sind, haben meistens ihren
> Ursprung in einem Fehler ganz wo anders.
Genau so wahr's.

Ich bin alle Dateien Zeile für Zeile durchgegangen und habe genau 
überlegt ob die Vorgehensweise stimmt.
Ich habbe alle möglichen Werte durchprobiert.
(Alle Kombinationen habe ich nicht durchprobiert, da es einfach zu lange 
gedauert hätte. Ich habe aber eine Stunde lang den Zufallsgenerator 
Kombinationen ausspucken lassen.)

Aber bis auf einige Optimierungsmöglichkeiten habe ich nichts gefunden.

@Michael
Bei diesem Fehler hätte es nichts gebracht den Quellcode des Projekts zu 
schicken.
Der Fehler war übrigens in der Zeile 136.

Der Fehler war übrigens fieserweise nicht im eigentlichen Projekt, 
sondern im Programm das die Ausgaben des Projekts auf Richtigkeit 
überprüft.

von Mark B. (markbrandis)


Lesenswert?

Bernhard schrieb:
> Der Fehler war übrigens fieserweise nicht im eigentlichen Projekt,
> sondern im Programm das die Ausgaben des Projekts auf Richtigkeit
> überprüft.

Wie gesagt -

Mark Brandis schrieb:
> -Debugger benutzen, Breakpoint setzen und die Funktion auf der
> Zielplattform Schritt für Schritt durchsteppen, notfalls hier mit
> Testarrays als Eingabe arbeiten weil man die Daten ja dann nicht in
> Echtzeit (über irgendeine Schnittstelle) bekommt

Für einen einzelnen Zyklus (oder wenige Zyklen) kann/soll man das 
durchaus mal von Hand prüfen. Und dann sieht man ja, dass auf dem 
Zielsystem das richtige Ergebnis herauskommt, und kann bei einer 
Diskrepanz zur Prüfsoftware diese sogleich in Gewahrsam nehmen.

von Bernhard (Gast)


Lesenswert?

Mark Brandis schrieb:
> Für einen einzelnen Zyklus (oder wenige Zyklen) kann/soll man das
> durchaus mal von Hand prüfen. Und dann sieht man ja, dass auf dem
> Zielsystem das richtige Ergebnis herauskommt, und kann bei einer
> Diskrepanz zur Prüfsoftware diese sogleich in Gewahrsam nehmen.

Wie ich schon geschrieben habe, hat sich der Fehler bei manuellem Prüfen 
nicht gezeigt.

Er ist nur beim normalen Programmablauf aufgetreten.

von Karl H. (kbuchegg)


Lesenswert?

Bernhard schrieb:

> Der Fehler war übrigens fieserweise nicht im eigentlichen Projekt,
> sondern im Programm das die Ausgaben des Projekts auf Richtigkeit
> überprüft.

Dann ist dieses Programmnichts wert, wenn es dir im Fehlerfall nicht 
gestattet den (seiner Meinung) nach fehlerhaften Fall nachzuvollziehen. 
Soweit nachzuvollziehen, dass du aus diesem Prüfprogramm die notwendigen 
Input Daten erhältst, mit denen du die Berechnung kontrollieren kannst.

von Michael B. (mb_)


Lesenswert?

Michael Roek-ramirez schrieb:
> Bei einem Rotierbefehl RLC/RRC ist vorher das Carry nicht richtig
> gesetzt....und je nach Aktivitaeten  im Interrupt kann's auch mal falsch
> sitzen ;-)

Dann ist aber der Interrupthandler auch noch defekt. Wenn der Handler 
das flag verändert, muss er dafür sorgen, dass es wieder zurückgesetzt 
wird.
Oder was passiert hier:

CLC
<-- Interrupt
RLC
RRC
...

von Bernhard (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Dann ist dieses Programmnichts wert, wenn es dir im Fehlerfall nicht
> gestattet den (seiner Meinung) nach fehlerhaften Fall nachzuvollziehen.
> Soweit nachzuvollziehen, dass du aus diesem Prüfprogramm die notwendigen
> Input Daten erhältst, mit denen du die Berechnung kontrollieren kannst.

Jepp

Der Fehler war da nicht in der Fehleranalyse selbst, sondern in der 
Datenerfassung.
Und wenn die erfassten Daten fehlerhaft sind, kann man die Daten noch so 
oft händisch nachrechnen und auf pausibilität überprüfen.
Dass Ergebnis stimmt immer mit dem Analyseprogramm überein.
(Außer man verrechnet sich.)

Desswegen habe ich ja auch so lange an der falschen Stelle nach dem 
Fehler gesucht.

Aber jetzt Schwamm drüber über die ganze Sache.

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.