Verrückter Fehler mit gelöschten Variablen

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    Aufgrund technischer Veränderungen ist der Mailverkehr innerhalb des Forums (Private Nachrichten) nur noch eingeschränkt möglich. Die Einschränkung ist notwendig, um zusätzliche Betriebskosten für das Forum zu vermeiden. Näheres zu den Hintergründen im Thread "Aktuelles zum Forum".Wir bitten um Verständnis.

    Hinweis kann nach Kenntnisnahme deaktiviert werden!

    • Verrückter Fehler mit gelöschten Variablen

      Hallo,

      ich habe einen verrückten Fehler den ich mir nicht erklären kann.

      Meine Software rennt soweit gut und ich war eben am verfeinern und verbessern. Ich schreibe meist alles einfach so runter und dann, wenn die Funktionalität passt, dann fange ich an das ganze zu verbessern wo es geht.

      Ich deklariere folgende Variablen:

      Quellcode

      1. DIM Eedummy AS ERAM BYTE ' AVR bug in eeram
      2. DIM modusEeprom AS ERAM BYTE ' save the value of discharge mode
      3. DIM modus AS BYTE
      4. DIM oledViewEeprom AS ERAM BYTE ' save the value of OLED view
      5. DIM oledView AS BYTE ' Specifies which display of a view is shown
      6. DIM oledSwitch AS BIT ' Ensures the triggering of the oled changeover in intervals
      7. DIM switch AS BYTE
      8. DIM abstand(9) AS STRING * 11
      9. DIM Ddata(1024) AS BYTE ' Display data buffer
      10. DIM hspEin AS BIT ' Beinhaltet den aktuellen Zustand der Hochspannung
      11. DIM hspEinAlt AS BIT
      12. DIM error AS BYTE ' Beinhaltet den aktuellen Zustand der Fehler
      13. 'DRECK
      14. DIM L AS SINGLE ' Abstand Elektrode zur Rollenoberfläche
      15. DIM D AS SINGLE ' Rollendurchmesser
      16. DIM V AS SINGLE ' Bahngeschwindigkeit
      17. DIM D1 AS SINGLE ' Materialstärke
      18. DIM test AS SINGLE
      19. DIM adcIpos AS WORD ' Übermittelter positiver Strom in Digit
      20. DIM iIstPos AS LONG
      21. 'DRECK ENDE
      22. DIM mnuSelect AS BYTE
      23. DIM mnuSelectOld AS BYTE
      24. DIM durchmesserEeprom AS ERAM WORD
      25. DIM durchmesser AS WORD
      26. DIM durchmesserLow AS BYTE AT durchmesser OVERLAY
      27. DIM durchmesserHigh AS BYTE AT durchmesser + 1 OVERLAY
      28. DIM abstandElektrodeEeprom AS ERAM WORD
      29. DIM abstandElektrode AS WORD
      30. DIM abstandElektrodelow AS BYTE AT abstandElektrode OVERLAY
      31. DIM abstandElektrodeHigh AS BYTE AT abstandElektrode + 1 OVERLAY
      32. DIM staerkeEeprom AS ERAM WORD
      33. DIM staerke AS WORD
      34. DIM staerkeLow AS BYTE AT staerke OVERLAY
      35. DIM staerkeHigh AS BYTE AT staerke + 1 OVERLAY
      36. DIM geschwindigkeitEeprom AS ERAM WORD
      37. DIM Geschwindigkeit AS WORD
      38. DIM GeschwindigkeitLow AS BYTE AT Geschwindigkeit OVERLAY
      39. DIM GeschwindigkeitHigh AS BYTE AT Geschwindigkeit + 1 OVERLAY
      Alles anzeigen
      Ein Paar Variablen sind mit " 'DRECK / DRECKE ENDE' " markiert und genau um diese geht es. Keine dieser Variablen benötige ich im code. Sie werden nicht verwendet. Lösche ich sie aber, dann spinnt meine Software. Egal ob ich alle lösche oder eine davon. Er kompiliert sauber durch und die Software spinnt.

      Jetzt wird es noch verrückter. Kopiere ich den Block an eine andere Stelle. Z.B. unter die letzte Variablen Deklaration in Zeile 51. Also einfach Copy/Paste, dann spinnt meine Software auch. Kopiere ich sie wieder dahin wo sie jetzt sind, dann geht wieder alles.

      Noch verrückter: Benenne ich sie um, in irgend etwas dann geht die Software auch. Sie werden also definitiv nicht benötigt. Dürfen heißen wie sie wollen, müssen nur da sein und genau an dieser Stelle......

      Tja und nun die Frage, wie kann das sein, dass Variablen, die keiner braucht so stören wenn man sie entfernt und selbst dann stören, wenn man ihre Deklaration in eine andere Zeile kopiert?

      Gruselig oder?

      Grüße

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Snatch ()

    • Hallo,

      hier der komplette Code. Aber bitte nicht zu genau hinschauen. Ist die unaufgeräumte und unoptimierte Version.
      Es geht mit auch mehr um das Problem mit den Variablen.

      Der gesamte Code ist zu lange sagt das Forum. Daher kann ich ihn nicht posten. Aber nochmal zum Verständnis. Die Variablen werden im gesamten Code nicht verwendet. Dennoch spinnt ein Teil der Software, wenn ich sie lösche oder auch nur in eine andere Zeile verschiebe. Umbenennen kann ich sie. z.B. in "hallo1" etc. Software geht dann. Das ist doch komisch oder?

      Quellcode

      1. $REGFILE = "m644def.dat"
      2. $CRYSTAL = 8000000 $hwstack = 80
      3. $swstack = 80
      4. $framesize = 100
      5. Config Clockdiv = 1



      Grüße und Danke
    • Welche Bascom-Version benutzt du?

      Ich habe die aktuelle und bei mir gehts.

      Allerdings habe ich den Font Arial32x32 nicht und deshalb die Zeile auskommentiert und statt dessen nur ein Label "arial32x32:" gesetzt.

      Schau mal in den Code-Explorer ein, da werden einige Fehler angezeigt.
      Bereinige die erst mal, dann sehen wir weiter.
      Bildschirmfoto vom 2022-06-01 16-28-55.png
    • Snatch schrieb:

      Tja und nun die Frage, wie kann das sein, dass Variablen, die keiner braucht so stören wenn man sie entfernt und selbst dann stören, wenn man ihre Deklaration in eine andere Zeile kopiert?
      Hallo Snatch,
      wenn die Variablen an der Stelle stehen, verhindern sie, dass die nachfolgenden Variablen durch Überschreitung der Arraydefinition von Ddata(1024) überschrieben werden.
      In der Sub Lcd_set_pixel wird die Variable Zeiger berechnet. Sollte ihr Wert größer als 1024 werden, werden die Variablen überschrieben, die direkt nach Ddata(1024) dimensioniert werden.

      Wenn ich dein Programm im Simulator laufen lasse, sehe ich dort Werte bis 1040 für die lokale Variable Zeiger. Also werden die nächsten 16 Byte nach Ddata überschrieben.
    • Franz schrieb:

      Snatch schrieb:

      Tja und nun die Frage, wie kann das sein, dass Variablen, die keiner braucht so stören wenn man sie entfernt und selbst dann stören, wenn man ihre Deklaration in eine andere Zeile kopiert?
      Hallo Snatch,wenn die Variablen an der Stelle stehen, verhindern sie, dass die nachfolgenden Variablen durch Überschreitung der Arraydefinition von Ddata(1024) überschrieben werden.
      In der Sub Lcd_set_pixel wird die Variable Zeiger berechnet. Sollte ihr Wert größer als 1024 werden, werden die Variablen überschrieben, die direkt nach Ddata(1024) dimensioniert werden.

      Wenn ich dein Programm im Simulator laufen lasse, sehe ich dort Werte bis 1040 für die lokale Variable Zeiger. Also werden die nächsten 16 Byte nach Ddata überschrieben.
      Vielen lieben Dank, das war es. Da wäre ich aber nie darauf gekommen. Ist das normal dass der dann einfach die nächst folgenden Variablen überschreibt? Sollte ja eigentlich nicht passieren und eher in einem Fehler enden oder?

      Dennoch, ich habe die Ddata nun auf 1024 begrenzt und der Fehler ist behoben.

      Grüße und Danke
    • Mitch64 schrieb:

      Welche Bascom-Version benutzt du?

      Ich habe die aktuelle und bei mir gehts.

      Allerdings habe ich den Font Arial32x32 nicht und deshalb die Zeile auskommentiert und statt dessen nur ein Label "arial32x32:" gesetzt.

      Schau mal in den Code-Explorer ein, da werden einige Fehler angezeigt.
      Bereinige die erst mal, dann sehen wir weiter.
      Bildschirmfoto vom 2022-06-01 16-28-55.png
      Danke auch dir, dass du es dir angeschaut hast. Ich nutze die 2.0.8.5. Zum Glück hat Franz die Lösung gehabt. Die Fehler im Code Explorer werden nun behoben und der Code optimiert.

      Vielen Dank
    • Snatch schrieb:

      Sollte ja eigentlich nicht passieren und eher in einem Fehler enden oder?
      Nein, denn zur Zeit des kompilierens weiß der Kompiler nicht dass da irgend ein Wert auch größer werden kann und das RAM damit überschreibt und zur Laufzeit wiederum weiß der Kontroller nicht wo eine Variable endet oder beginnt (ist dann besonders teuflisch bei Strings die im Ablauf länger werden als zum Zeitpunkt der Kompilierung.
      Er weiß sehr wohl dass es nicht funktioniert einen Word-Wert in in ein Byte zu schreiben und zeigt dies dann mit einem Fehler an genauso wie es in einem Fehler münden wird wenn du versuchst im Programm einem String eine zu lange Zeichenkettte zuzuweisen (bei einer Stringverkettung wiederum wird gar kein Fehler angezeigt weil der Kompiler zur Kompilierzeit gar nicht weiß ob der String schon Überlänge hat (allenfalls gibt es Warnungen aber die auch nicht immer)
      Der Controler weiß nur dass er für eine bestimmte Variable x Byte Platz zu verwenden hat und kann. Der weiß eben nicht wie groß die Dimension bei Arrays ist und wie weit ein String reicht.
      Der schreibt und ließt da nur entsprechend den Anforderungen des Programmes im RAM.

      Mit DIM wird der Kompiler nur angewiesen entsorechend Platz im RAM zu reservieren mehr nicht, zur Laufzeit sind diese Dimensionen dann unbekannt und es kommt eben zu den beobachteten Effekten wenn man sich dann daran nicht hält.
      Der kennt da auch nicht die Variable X sondern hat dein X=5 nur in entsprechenden Maschinencode übersetzt und spricht damit nur die entsprechende Speicherzelle im RAM an denn zur Laufzeit wiederum kennt der Kontroller gar keine Variable X sondern nur eine Adresse im RAM.
    • Hallo Pac-Man,
      du musst halt vermeiden, dass in einem Array größere Indices als erlaubt verwendet werden.
      Das geht zum einen indem du sicherstellst, dass dies niemals zutrifft. Oder du machst einen Check jedesmal bevor du einen Index verwendest, was aber evtl. viel Programmcode und laufzeot kostet.
      Bei Strings ist es etwas komplizierter. Du müsstest dazu zunächst die Einzelteile in der Länge überprüfen bevor du sie zusammensetzt. Das ist natürlich ziemlich aufwendig. Also auch hier wieder sicherstellen, dass es nicht passiert.
      Strings und Arrays sind eh die einzigen Datentypen, die eine flexible Länge haben, sodass man nur dort aufpassen muss.
    • Ja, das ist nicht so einfach. Hirn einschalten hilft natürlich immer ;)
      Wenn du z.B. eine Routine hast, die Daten aus dem UART einliest und in einen String anhängt (sehr aufwendig), dann solltest du dabei mitzählen. Das geht wesentlich schneller als jedesmal die Stringlänge zu bestimmen. Und es verhindert, dass es Probleme mit Überschreiben gibt. Ich verwende dazu normalerweise Byte-Arrays die ich per Overlay über einen entsprechend langen String lege. Dazu habe ich einen Zähler, der angibt, wo ich beim nächsten Mal hinschreiben muss oder wo ich zuletzt geschrieben habe.
      Den String verwende ich dabei nur, wenn es einfacher ist und Sinn macht, wie z.B. für ein Print oder LCD-Ausgabe.
      Strings sind sowieso ein leidiges Thema, wo man leicht übersieht, wie aufwendig das ist. Ich vermeide das wo immer es geht.

      Bei Arrays mache ich es tatsächlich sehr häufig, den Index vor dem Verwenden zu überprüfen. Zumindest dann, wenn ich nicht vorab weiß, wieviele Bytes geschrieben werden. Ein Byte oder Word Vergleich kostet nicht viel und ist da sehr sicher.