Hallo zusammen
Ich habe einen uint8_t Wert, der als int interpretiert werden soll. Ich
arbeite auf einem STM32G474 mit IAR.
Bei +1 kommt 0x01 daher, bei -1 0xFF, alles korrekt. Dann habe ich den
cast auf (int8_t) gemacht aber 0xFF beleibt 0xFF. Jemand eine Idee?
Die Screenshots vom Debugger sind in den Bilder zu sehen.
static void on_cmd_wheel_turned_f(const uint8_t *data_p, uint_fast16_t
data_length) {
/*-- Local Variables
---------------------------------------------------------------*/
union tDATA_Event_RemoteControl t_RemoteControl;
uint8_t response_a[SCP_PAYLOAD_MAX_LENGTH];
size_t response_len = 0;
int8_t nWheelInc = 0;
uint16_t nLogValue = 0;
/*-- Code Statements
---------------------------------------------------------------*/
nWheelInc = (int8_t)(BUF_READ_BE_U8_F(data_p, 0));
Mach F. schrieb:> Dann habe ich den cast auf (int8_t) gemacht aber 0xFF> beleibt 0xFF. Jemand eine Idee?
Du hast beschrieben, was du gemacht hast und was dann passierte.
Was hast du denn erwartet?
Hast du ein Problem mit dem Verhalten des Compilers, oder nur mit der
Darstellung durch den Debugger? Lässt sich die Art einstellen, wie der
Debugger Werte anzeigt, z.B. hex/dez?
(prx) A. K. schrieb:> Hast du ein Problem mit dem Verhalten des Compilers, oder nur mit der> Darstellung durch den Debugger? Lässt sich die Art einstellen, wie der> Debugger Werte anzeigt, z.B. hex/dez?
Danke für den konstruktiven Beitrag.
Die Darstellung ist mir egal, die if Anweisung danach mit >= 0
funktioniert so nicht, denn -1 ist ja wie im Debugger zu sehen ist 0xFF
und darum ist die if >= 0 bei 0xFF true, was ich genau nicht möchte. Ich
muss alle negativen Werte im else behandeln. Das ist die wirklich
einfache Aufgabe, aber da es nicht funktionierte habe ich im Debugger
den Wert angeschaut und war etwas erstaunt, dass ich 0xFF anstatt -1
angezeigt bekam.
... Die ersten Antworten im Thread haben dies wahrscheinlich nicht
bemerkt.
Mach F. schrieb:> Die Darstellung ist mir egal, die if Anweisung danach mit >= 0> funktioniert so nicht, denn -1 ist ja wie im Debugger zu sehen ist 0xFF> und darum ist die if >= 0 bei 0xFF true, was ich genau nicht möchte.
Compiler und Debugger sind zwei völlig verschiedene paar Stiefel. Es ist
durchaus möglich, dass der Debugger in deiner Einstellung alle 8-Bit
Werte unabhängig vom deklarierten Vorzeichen so anzeigt, wie oben
abgebildet, obwohl der Compiler 0xFF im if als negativen Wert
behandelt.
Deshalb meine Frage danach, ob du ein Problem mit dem Verhalten des
Compilers hast, oder aufgrund der Anzeige des Debuggers nur eines
vermutest.
(prx) A. K. schrieb:> Deshalb meine Frage danach, ob du ein Problem mit dem Verhalten des> Compilers hast, oder aufgrund der Anzeige des Debuggers nur eines> vermutest.
ja habe ein Problem mit dem Compiler, denn der Compiler behandelt den
Wert 0xFF als positiven Wert, sprich die if >= 0 ist true, was nicht
sein sollte. Wenn ich einen Breakpoint im else setze, wird dieser nicht
getriggert, auch bei 0xFF oder eben -1 nicht.
Wenn das Verhalten des Programms den Wert als positiv sieht, dann wird
es fällig, sich den erzeugten Code und die Registerinhalte per single
step oder breakpoint nicht auf C-Ebene anzusehen, sondern auf
Assembler/Register-Ebene.
Vorsichtshalber sei noch erwähnt, dass das Verhalten von Typen mit
Vorzeichen bei Überlauf undefiniert ist. Ob das auch beim Cast zutrifft,
weiss ich gerade nicht - wenn ja, dann ist der Ausdruck (int8_t)0xFF
undefiniert und der Compiler immer im Recht, völlig egal was er macht.
Mich würde das allerdings beim Zielmarkt von IAR etwas überraschen.
Ich habe die Hardware jetzt nicht auf dem Tisch, aber werde das nochmals
versuchen Danke.
Jedenfalls spuckt mir der Compiler bei if (nWheelInc < -128) {
die Warning aus:
Warning[Pa084]: pointless integer comparison, the result is always false
Bei if (nWheelInc < -127) ist wie warning weg, was bei einem int8_t auch
so sein muss, warum das Verhalten der if Anweisung aber anders ist kann
ich mir im Moment nicht erklären, werde dies aber Morgen nochmals
genauer untersuchen. Es hat mich einfach stutzig gemacht, dass der
Debugger den Datentyp zwar mit int8_t angibt, aber die Darstellung nicht
auf Dezimal -1 wechselt, wobei dies nicht im Watch Window ist, das
könnte noch ein Versuch wert sein
Mach F. schrieb:> warum das Verhalten der if Anweisung aber anders ist kann> ich mir im Moment nicht erklären,
ich kenne den compiler nicht aber:
der Vergleichswert "0" ist ein signed int (also 32 Bit).
Den vergleichst Du mit einem sint8_t.
-> er wird vor dem Vergleich erst auf eine 32 Bit Zahl erweitert.
Eventuell wird dabei das Vorzeichen unterschlagen.
Gruß Anja
Anja schrieb:> Eventuell wird dabei das Vorzeichen unterschlagen.
Darf er nicht, denn int8_t ist in int vollständig enthalten und folglich
ist diese Konvertierung wohldefiniert.
Anja schrieb:> der Vergleichswert "0" ist ein signed int (also 32 Bit).
Danke Anja! Ich werde es mal so versuchen:
if (nWheelInc <= -1) {
oder würdest du if (nWheelInc <= ((int8_t)-1)) {
schreiben?
Das Ergebnis von (int8_t)255 ist zwar implementation defined, ich kann
mir aber nicht vorstellen, dass irgendein ARM-Compiler dafür bewusst
einen anderen Wert als -1 liefert. Unbewusst (d.h. auf Grund eines Bugs)
wäre dies zwar denkbar, aber unwahrscheinlich. Ob tatsächlich ein Bug
vorliegt, kann man dem erzeugten Assemblercode entnehmen.
Dass der Debugger 0xFF anzeigt, braucht dich nicht zu beunruhigen, da
die Hexadezimaldarstellung in C (also bspw. auch in printf) immer
vorzeichenlos ist. Wenn du den Debugger dazu bringen kannst, den Wert
dezimal anzuzeigen, wirst du ziemlich sicher die erwartete -1 sehen.
Etwas unschön finde ich an diesem Code das doppelte hin und her mit dem
Vorzeichen:
int8_t x = (int8_t) uint8_t
if (x >= 0) {
... = (uint8_t) x
Wäre da nicht
uint8t_t x = ...
if ((int8_t)x >= 0) {
... = x
besser?
Yalu X. schrieb:> Unbewusst (d.h. auf Grund eines Bugs)> wäre dies zwar denkbar, aber unwahrscheinlich.
Beim IAR ist das aber warscheinlicher als woanderswo ;)
@machfax
Der Mouseover des IAR Debuggers ist sehr unzuverlässig und zeigt meist
"irgendwas" an.
Der schnallt einfach nicht, dass es ein int ist und nutzt trotzdem die
Hex Darstellung.
Packe die Variable in das Watchfenster und stell von Hex auf Decimal um.
Mach F. schrieb:> if (nWheelInc < -128) {> die Warning aus:> Warning[Pa084]: pointless integer comparison, the result is always false
Verstehe ich irgendwas nicht? Wenn nWheelInc ein int8 ist, ist das doch
korrekt. Es kann nicht kleiner -128 werden und damit ist der Ausdruck
niemals true?
Du sagst doch selbst, beim Vergleich mit < -127 geht es, ja weil es noch
-128 sein kann.
Was übersehe ich, was ist die Erwartung?
Mach F. schrieb:> ja habe ein Problem mit dem Compiler,
Nach all dem, was du also so geschrieben hast, scheint das Problem doch
eher vor dem Computer zu sitzen. Es gibt keine fehlerfreie Software,
aber das ein gcc einen einfachen signed-Vergleich versemmelt, ist doch
eher unwahrscheinlich.
Da du aber keine aussagekräftige Sourcen zeigst, ist die ganze
Diskussion müßig. Zeig ein compilierbares Beispiel mit dem „Fehler“,
dann schauen wir weiter.
Oliver
Oliver S. schrieb:> Mach F. schrieb:>>> ja habe ein Problem mit dem Compiler,>> Nach all dem, was du also so geschrieben hast, scheint das Problem doch> eher vor dem Computer zu sitzen. Es gibt keine fehlerfreie Software,> aber das ein gcc einen einfachen signed-Vergleich versemmelt, ist doch> eher unwahrscheinlich.> Da du aber keine aussagekräftige Sourcen zeigst, ist die ganze> Diskussion müßig. Zeig ein compilierbares Beispiel mit dem „Fehler“,> dann schauen wir weiter.> Oliver
sehr sehr hilfreich... ich habe ja geschrieben dass der breakpoint nicht
getriggert wird. Natürlich sitzt das Problem vor dem Computer, die Frage
ist nur vor welchem ;-)
Große Auswahl gibts ja nicht...
Geh einfach mal davon aus, daß der Compiler einen int-Vergleich
fehlerfrei hinbekommt. Was dazu führt, daß der Fehler, wenn’s denn
überhaupt einer ist, woanders her kommt.
Ein Kandidat wäre z.B. scp_transmit..., daß das Array über die Grenzen
beschreibt, oder auch einfach Kompilierung mit Optimierung, die sich
schlicht im Debugger verwirrt, oder ein falsch initialisierter Stack,
oder was auch immer.
Da gibt es Unendliche viele Möglichkeiten, aber der int-Vergleich ist
mit Sicherheit nicht das Problem.
Hinner schrieb:> Hier gibt es weiteres Futter zum Nachlesen:>> Beitrag "ergebnis kann negativ werden, obwohl nur uint8_t verwendet> wird"
Ist eine andere Baustelle.
Oliver
Oliver S. schrieb:> Da gibt es Unendliche viele Möglichkeiten, aber der int-Vergleich ist> mit Sicherheit nicht das Problem.
Das denke ich auch nicht. scp_transmit funktioniert einwandfrei,
Optimierungen sind komplett deaktiviert. So wie ich das sehe, ist diese
"einfache" Abfrage doch nicht so einfach wie es auf den ersten Blick
aussieht -> Beitrag "ergebnis kann negativ werden, obwohl nur uint8_t
verwendet wird"
Ich finde es einfach nicht sehr konstruktiv, wenn hier im Forum immer
wieder direkt Leute angegriffen und als Idiot abgestempelt werden, und
das ist definitiv nicht das erste Mal dass ich dies (bei meinen wie auch
bei anderen Threads) sehe. Finde dies ehrlich gesagt schade.
Nochmal im Klartext:
Der Code, von dem du meinst, daß er fehlerhaft ausgeführt wird, lautet:
1
if(nWheelInc>=0){
2
...
3
}else{
4
...
5
}
Das ist so einfach, wie es aussieht. Ende der Diskussion.
Und wer Code als .png anhängt, hat gleich vom ersten Beitrag an ein
schlechtes Standing. Ist leider auch so.
Oliver
Oliver S. schrieb:> Das ist so einfach, wie es aussieht. Ende der Diskussion.
korrekt, dann erklär mir doch bitte mal warum bei einem Wert von 0xFF
nicht die else Anweisung ausgeführt wird.
Auf das png muss ich nicht weiter darauf eingehen, es war eine schnelle
Möglichkeit, den Teil vom Code zu zeigen, nicht mehr und nicht weniger,
und scheinbar hat es auch sein Ziel erreicht. Leider bin ich zu blöd um
zu sehen, wie man Code-Statements hier einfügen kann, entschuldige
bitte.
Mach F. schrieb:> Leider bin ich zu blöd um> zu sehen, wie man Code-Statements hier einfügen kann,
Das steht in dem grauen Rahmen um das Edit-Fenster, in dem du den
Beitrag schreibst, direkt unter der Überschrift „Formatierung“
Dirk B. schrieb:> Das steht in dem grauen Rahmen um das Edit-Fenster, in dem du den> Beitrag schreibst, direkt unter der Überschrift „Formatierung“
Danke
Mach F. schrieb:> Dann habe ich den> cast auf (int8_t) gemacht aber 0xFF beleibt 0xFF.
Ein cast veraendert nie die Daten selbst, sondern nur deren
interpretation.
BUF_READ_BE_U8_F(..) scheint ein Macro zu sein, was macht denn der
Praeprozessor daraus?
Mach F. schrieb:> korrekt, dann erklär mir doch bitte mal warum bei einem Wert von 0xFF> nicht die else Anweisung ausgeführt wird.Oliver S. schrieb:> Da gibt es Unendliche viele Möglichkeiten, aber der int-Vergleich ist> mit Sicherheit nicht das Problem.
Wenn solche Fehler an Stellen auftreten, wo keine Fehler auftreten
können, liegt das Problem häufig ganz woanders. Startup-Code,
Linkerscript, sämtlicher anderer Code im Projekt, was auch immer. Nur
nicht da, wo du suchst.
Du suchst an der falschen Stelle.
Oliver
Arduino Fanboy D. schrieb:> Mladen G. schrieb:>> Ein cast veraendert nie die Daten selbst, sondern nur deren>> interpretation.>> Hei hei hei....> Ein cast konvertiert die Daten.
Ja. Nein. Vielleicht.
Zwischen Ganzzahltypen wird das Bitmuster übernommen.
Sind Fließkommatypen im Spiel, wird gewandelt.
Also als Backup-Lösung werde ich dies dann implementieren, aber
interessieren würde es mich trotzdem, warum dies mit dem cast nicht
geht. Ich melde mich, sobald ich dies mit dem cast ausprobiert habe.
Wie andere schon schrieben: der Code ist zwar nicht schön, macht aber
das, was du willst. Such den Fehler woanders. Debugger sind notorisch
unzuverlässig - schau dir den generierten Code an. Evtl wird das Lesen
des Buffers ja verschoben und der Buffer, auf den data_p zeigt, ist doch
nicht so "const" und scp_transmit ändert den? Oder du hast den falschen
code gebrannt ...
Mach F. schrieb:> Update, funktioniert so
Das mag ja sein, aber magst du soetwas abgeben?
Hast du dir, wie oben schon vorgeschlagen, den generierten Assemblercode
mal angesehen? Also von der Version die nicht funktioniert? Bzw. wenn
der Debugger auf der scheinbar falsch ausgeführten if Anweisung steht,
dann(!) den Wert der Variablen nWheelInc angeschaut? Oben im
Eröffnungspost liegen noch 2 Statements vor der if-Anweisung. Vielleicht
machen die etwas kaputt?
Das Pflaster, was du da jetzt drauf geklebt hast, ich würde das nicht
abgeben mögen. Würde ich maximal auf meinem Basteltisch machen wenn ich
keine Zeit habe. Aber im Job nicht.
Am Ende ist es natürlich deine Entscheidung.
Edit: Aus Neugier... was ist das für eine CPU und welcher Compiler.
Mach F. schrieb:> Es ist ein STM32G474VE
Ach stand oben ja schon, dass hatte ich dann übersehen weil ich nur in
Codeschnipsel gesehen habe.
Sieht jetzt ja etwas besser aus. Aber trotzdem ist es schräg, dass die
if-Anweisung so wie am Anfang beschrieben, nicht funktioniert. Es steht
ja (angeblich) 0xFF drin was negativ ist.
900ss D. schrieb:> Aber trotzdem ist es schräg, dass die> if-Anweisung so wie am Anfang beschrieben, nicht funktioniert. Es steht> ja (angeblich) 0xFF drin was negativ ist.
Das ist beim IAR 8.x leider gang und gäbe.
Das hab ich schon so oft erlebt, dass es nicht mehr feierlich ist.
Beim IAR 7.x gabs diese Probleme nicht.
Offensichtlich hat der Probleme beim recompilen wenn man nur etwas an
einer Funktion ändert, ein Rebuild All löst das dann meistens.
(Beim GCC hab ich sowas jedenfalls noch nie erlebt, egal welche Version)
Beispiel im Anhang!
Da war nichtmal ein cast im Spiel.
Es läuft nur ein Task und niemand weiter schreibt die Variable.
Der Debugger steht auf dem if -> das bool steht auf true.
Drückste einmal F10 für Step und du landest im else Zweig, auf einmal is
die Variable false.
Hä was? Ein Rebuild All löste das Problem.
Der IAR bekommt auch des öfteren Änderungen in Headern nicht mit, da hab
ich mir auch schonmaln Wolf gesucht.
Ich kann daher Mach F. (und der Firma in der er arbeitet) nur empfehlen
sich nach einem ordentlichen Compiler/IDE umzusehen!
Mach F. schrieb:> Es ist ein STM32G474VE-T6, IAR 8.50.9> Der cast auf (int8_t) auf den BUF_READ_BE_U8_F funktioniert nicht
Ganz ehrlich, ein Compiler, der bei solch grundlegenden Dingen versagt,
gehört sofort in die Tonne. Da das Ding zudem noch nicht ganz wenig Geld
gekostet hat, wirds jetzt wirklich Zeit für einen bitterbösen Brief an
IAR.
Allerdings erst, nachdem nachgeweisen wurde, daß der Compiler wirklich
Murks macht, und nicht nur der Debugger, oder der Fehler von woanders
kommt.
Oliver
Oliver S. schrieb:> wirds jetzt wirklich Zeit für einen bitterbösen Brief an IAR.
Bingt bei denen nix.
Oliver S. schrieb:> Allerdings erst, nachdem nachgeweisen wurde, daß der Compiler wirklich> Murks macht, und nicht nur der Debugger,
Is beim IAR ja aus der selben Quelle.
Mw E. schrieb:> Das ist beim IAR 8.x leider gang und gäbe
Hab ich bisher nicht benutzen dürfen. Bestätigt aber auch meine
bisherige Meinung, nichts verpasst zu haben. ;)
Mach F. schrieb:> Danke
OT: Ja das funktioniert schon, ist aber nicht mehr direkt klar lesbar,
was da gemacht werden soll, was unschön ist. Und kürzer wird der
generierte Code auch nicht.
900ss D. schrieb:> Keiner N. schrieb:>> das if kannst du auch wehschmeißen>> Was für einen Vorteil hätte das? Außer das man die Tastatur schont?
Man kann die Variable richtig initialisieren, wenn man sie definiert
1
boolbWheelNegative=(int8_t)nWheelInc<0;
Warum wurde die Variable vorher mit false initialisiert?
mh schrieb:> Man kann die Variable richtig initialisieren, wenn man sie definiert
Der Wert von nWheelInc ist noch nicht bekannt. Ja klar kann man alles
hinschustern und noch mehr schlecht lesbaren Code produzieren.
Und ohne Klammern geht das bei "uns" auch nicht durch Rulechecker wenn
der Compiler nicht schon eine Warnung wirft. Aber das ist alles OT hier.
900ss D. schrieb:> Und ohne Klammern geht das bei "uns" auch nicht durch Rulechecker
Warum nicht? Der Compiler wirft an der Stelle keine Warnung und es ist
ganz klar definiert das der '=' eine kleinere Priorität hat als der '<'.
900ss D. schrieb:> mh schrieb:>> Man kann die Variable richtig initialisieren, wenn man sie definiert>> Der Wert von nWheelInc ist noch nicht bekannt.
Da wo das If-Statement steht ist nWheelInc bekannt. Die Definition von
bWheelnegativ kommt da hin, wo sie das erste mal gebraucht wird und
nicht an den Anfang der Funktion.
> Ja klar kann man alles hinschustern und noch mehr schlecht lesbaren Code >
produzieren. Und ohne Klammern geht das bei "uns" auch nicht durch
> Rulechecker wenn der Compiler nicht schon eine Warnung wirft. Aber das> ist alles OT hier.
Bei "euch" ist das so. Bei uns würde so eine Definition mit vermutlich
unsinniger Initialisierung nicht durchs Review kommen, da es die
Wartbarkeit der Software reduziert.
Mach F. schrieb:> Update, funktioniert so:
Sorry, aber ich finde es trotzdem einen Fehler, eine uint8_t Variable zu
erstellen, wenn man diese später als int verwenden will. So weit ich
sehe, ist doch nur das Makro das Problem - und da steht nicht viel drin.
Mach F. schrieb:> ((((uint8_t)(*(((const uint8_t *)buffer_p) + (offset) + 0))) << 0))
Warum das ganze nicht entsprechend anpassen und komplett mit int8_t
arbeiten?
Christian H. schrieb:> Warum das ganze nicht entsprechend anpassen und komplett mit int8_t> arbeiten?
Weil dieses Makro normalerweise immer für uint benötigt wird, nur in
diesem speziellen Fall müssen die Daten vom RX Buffer als signed
interpretiert werden und ich wollte dasselbe Makro verwenden. Ja ich
könnte dies jetzt anpassen und ein spezielles Makro für diesen einen
Fall erstellen oder den Buffer in uint auslesen und danach casten, was
ich jetzt auch so mache.
Mw E. schrieb:> Ich kann daher Mach F. (und der Firma in der er arbeitet) nur empfehlen> sich nach einem ordentlichen Compiler/IDE umzusehen!
Also IAR ist jetzt kein Bastler-Compiler, bin ansonsten wirklich
zufrieden, meine Meinung. Dies ist aber definitiv nicht schön und kann
Stunden kosten...
Mach F. schrieb:> Die Darstellung ist mir egal, die if Anweisung danach mit >= 0> funktioniert so nicht, denn -1 ist ja wie im Debugger zu sehen ist 0xFF> und darum ist die if >= 0 bei 0xFF true, was ich genau nicht möchte. Ich> muss alle negativen Werte im else behandeln. Das ist die wirklich> einfache Aufgabe, aber da es nicht funktionierte habe ich im Debugger> den Wert angeschaut und war etwas erstaunt, dass ich 0xFF anstatt -1> angezeigt bekam.
Hallo,
in wie weit könnten die in folgendem Link beschriebenen "integral types"
des C-Standards das sonderbare Verhalten erklären?
https://www.iar.com/knowledge/support/technical-notes/general/integral-types-and-possibly-confusing-behavior/
Ein rudimentärer cast von uint8_t auf int8_t liefert laut dem
angehängten Screenshot das erwartete Ergebnis und der "else" Zweig wird
durchlaufen.
Kannst Du an Hand der Variablenwerte im Watch-Window, bzw. des
generierten Assembler-Codes eingrenzen, was die fehlerhafte if-Abfrage
in Deinem Code verursacht?
Gruß,
Michael
Michael F. schrieb:> in wie weit könnten die in folgendem Link beschriebenen "integral types"> des C-Standards das sonderbare Verhalten erklären?
Gar nicht.
Der Code, der angeblich nicht funktioniert, lautet:
1
int8_tnWheelInc=0;
2
nWheelInc=(int8_t)(BUF_READ_BE_U8_F(data_p,0));
3
if(nWheelInc>=0){
4
...
5
}else{
6
...
7
}
Da wird nichts promoted, nWheelInc selber wird nicht mal gecastet,
sondern nur zugewiesen und dann verglichen. Da kann und darf nichts
schiefgehen, was mit der Sprachdefinition von C zu tun hat.
Alles drumherum allerdings schon
Oliver
Mach F. schrieb:> ((((uint8_t)(*(((const uint8_t *)buffer_p) + (offset) + 0))) << 0))
Das Ergebnis davon ist aber kein "uint8_t", sondern "int", mit
Wertebereich 0..255. Wird das nach int8_t konvertiert, ist das Verhalten
für 128..255 undefiniert.
(prx) A. K. schrieb:> Wird das nach int8_t konvertiert, ist das Verhalten für 128..255
... implementation-defined.
Das Verhalten müsste also bei IAR irgendwo dokumentiert sein.
Hier wird mal wieder typisches Voodoo-Programing betrieben. Korrekter
C-Code tut nichts das Erwartete und wird ziellos solange verändert, bis
es passt. Das ursprüngliche Problem bleibt bestehen und der Fehler wird
auf den Compiler geschoben. Meiner Erfahrung nach, ist das fast immer
falsch, der Compiler ist korrekt und der Fehler liegt beim
Programmierer. Wie auch immer: einem ist nicht geholfen - wenn der
Compiler defekt ist, wird der Fehler auch in anderen Programmteilen
vorkommen und man hat es nur noch nicht gefunden; das gleiche passiert,
wenn die Programmierlogik verkehrt ist. Ziel sollte immer sein, den
Fehler zu verstehen!
Ist es denn so schwierig, im Debugger mal kurz auf Assembler-Mode
umzuschalten und nachzuschauen, ob wirklich der Code produziert wurde,
den man erwartet hat? Dann weiß man sofort, ob der Compiler
fehlerhaften Code produziert hat.
Je länger ich drüber nachdenke, desto wahrscheinlicher kommt mir das
"const" als Fehlerursache vor:
1
Pseudocode ohne const (push/pop temp register):
2
load reg,*data_p
3
push reg
4
call scp_transmit
5
pop reg
6
comp reg,0
7
...
8
9
Pseudocode mit const (reload temp register from const-pointer):
10
load reg,*data_p // evtl ganz wegoptimiert
11
call scp_transmit
12
load reg,*data_p
13
comp reg,0
14
...
Falls der Buffer, auf den data_p zeigt, während des Aufrufs von
scp_transmit verändert wird, ist der Fehler sofort offensichtlich.
Also nochmal: besteht die Möglichkeit, dass während des Aufrufs von
scp_transmit, die Daten, auf die data_p zeigt, verändert werden? Egal
ob durch Nutzung des gleichen Buffers von scp_transmit oder durch
längere Laufzeit mit zwischenzeitlichen Interrupts?
Falls ja, musst du dir überlegen, ob das Weglassen von "const" wirklich
das Problem löst ...
Cyblord -. schrieb:> Wer solche Makros benutzt hat die Kontrolle über seinen Code verloren.
Ja, schön ist anders...
Wobei selbst mit dem Makro die if-Anweisung in meinem rudimentären
Beispielprojekt den "else" Zweig durchläuft.
(prx) A. K. schrieb:> Das Verhalten müsste also bei IAR irgendwo dokumentiert sein.
Indirekt ist es das in dem o.a. link:
Michael F. schrieb:> in wie weit könnten die in folgendem Link beschriebenen "integral types"> des C-Standards das sonderbare Verhalten erklären?> https://www.iar.com/knowledge/support/technical-notes/general/integral-types-and-possibly-confusing-behavior/
Beispiel 3 kommt dem am nächsten. Danach werden die unteren 8 bit des
int für den int8_t genommen, und damit müsste der Vergleich >=0
funktionieren. Schief ginge das mit Werten < -128, wenn die
Vorzeichenbits aus dem letzten Byte rausrutschen, da der aber aus einem
uint8_t promoted wurde, kommt das nicht vor.
Oliver
Das Makro ist nicht von mir, aber egal, es geht auch ohne Makro mit dem
cast nicht, also schön oder nicht schön, es liegt NICHT am Makro, ist
soeben im LiveWatch aufgenommen worden.
Mach F. schrieb:> es liegt NICHT am Makro
Kannst du an der Stelle nicht sehen da deine Variable bWheelNegative
noch nicht existiert. Erst einen Step weiter. Und geladen wurde
nWheelInc richtig, steht 0xff drin.
Mach F. schrieb:> Das Makro ist nicht von mir, aber egal, es geht auch ohne Makro mit dem> cast nicht, also schön oder nicht schön, es liegt NICHT am Makro, ist> soeben im LiveWatch aufgenommen worden.
Es wurde ja jetzt schon ein paarmal nach dem Assemblercode gefragt, den
der Compiler daraus macht.
Kriegst du das hin?
Oliver
Achso, du meintest wahrscheinlich, dass der geladene Wert mit oder Makro
identisch ist. Dann vergiß meinen Post. Ich konnte ihn nicht mehr
löschen :)
Trotzdem wäre der nächste Step interessant gewesen.
Also der Debugger ist schon grenzwertig.
Er zeigt als Datentyp int8_t und den Wert als char plus uint8_t.
Da hätte ich jetzt von IAR mehr erwartet.
(Selbst VSCode mit GCC zeigt die Datentypen int8_t, uint8_t korrekt
an....)
Interessant, die Screenshots von Mach F. und Michael F. zeigen, dass
beide die Version IAR 8.50.9 genutzt haben. Bei Michael wird aber der
Wert im Watch Fenster als negativer Wert dargestellt.
Eine Frage an Mach: hast Du mal wirklich ein clean und rebuild all
gemacht?
Und noch eine blöde Frage:
Ihr habt nicht zufällig euch den Datentyp int8_t durch ein uraltes Makro
im Code ala
#define int8_t ....
verbastelt?
Hatte zwar auch schon Probleme mit der IAR Workbench, aber meistens lag
das Problem doch eher auf Programmiererseite...
Marc schrieb:> Also der Debugger ist schon grenzwertig.> Er zeigt als Datentyp int8_t und den Wert als char plus uint8_t.
Wie ich oben schon schrieb, ist es bei Hex-Zahlen nicht üblich, sie mit
Vorzeichen anzuzeigen, schon gar nicht im C-Umfeld. Die Hex-Schreibweise
dient ja primär dazu, das Bitmuster herauslesen zu können, was aber bei
negativem Vorzeichen, arg erschwert würde.
Marc schrieb:> Interessant, die Screenshots von Mach F. und Michael F. zeigen, dass> beide die Version IAR 8.50.9 genutzt haben. Bei Michael wird aber der> Wert im Watch Fenster als negativer Wert dargestellt.
Bei Michael wird er nicht hexadezimal, sondern dezimal und deswegen mit
Vorzeichen dargestellt. Ich schätze, dass man das Ausgabeformat im
Debugger irgendwo einstellen kann.
> [assembler.jpg]
Sieht vollkommen korrekt aus - macht genau das, was im C-Code steht.
Wäre natürlich hilfreich gewesen, zu wissen, welchen Wert R7 in der
grünen Zeile hat und wo jetzt überhaupt ein "Fehler" auftritt (das
ursprüngliche IF gibt's ja nicht mehr).
Yalu X. schrieb:> Die Hex-Schreibweise> dient ja primär dazu, das Bitmuster herauslesen zu können, was aber bei> negativem Vorzeichen, arg erschwert würde.
Bei Anzeige von "char" ist das natürlich so, da hätte ich ggf auch eine
dazu passende Hex Zahl. Aber der Debugger zeigt ja "int8_t" als Datentyp
an, da hätte ich erwartet, dass er automatisch den dezimaln Wert mit
Vorzeichen anzeigt.
Mach F. schrieb:> ich habe ja geschrieben dass der breakpoint nicht getriggert wird.
Dazu müsstest Du den Code Posten. Es ist je nach Optimierungsstufe
möglich, dass dort kein eigener Code ist.
Mache ein nop hin und zeig den Code.
foobar schrieb:> Sieht vollkommen korrekt aus
Sehe ich auch so. Ich schätze, dass danach in bWheelNegative auch der
erwartete Wert steht.
Aber der Code ist ja ein ganz anderer als der ursprüngliche, in dem der
Fehler auftrat. Zum einen gibt es dort die if-Anweisung, zum anderen
wird dort nWheelInc schon vor dem Aufruf von scp_transmit beschrieben.
Wer weiß, ob nicht in scp_transmit auf Grund eines Pufferüberlaufs o.ä.
nWheelInc überschrieben wird, so dass bei der if-Anweisung ein ganz
anderer Wert ankommt.
@Mach:
Hast du dir eigentlich in deinem ursprünglichen Code den Breakpoint auch
mal auf die if-Anweisung gesetzt und dir dort den Wert von nWheelInc
anzeigen lassen? In deinen bisherigen Screenshots sieht es so aus, als
ob du nur die korrekte Zuweisung in nWheelInc=... überprüft hast, nicht
aber, ob der Variableninhalt danach möglicherweise geändert wurde.
@Marc:
Marc schrieb:> Aber der Debugger zeigt ja "int8_t" als Datentyp an, da hätte ich> erwartet, dass er automatisch den dezimaln Wert mit Vorzeichen> anzeigt.
Ja, sinnvoller wäre das auf jeden Fall. Immerhin hat es Michael
geschafft, dem Debugger auch die Dezimaldarstellung zu entlocken.
Mach F. schrieb:> Oliver S. schrieb:>> Kriegst du das hin?> bitte schön
Schon ganz prima...
Wenn’s jetzt noch der nicht funktionierende Code wäre, und dazu als
Text, und nicht als Bild, wäre es noch besser...
Oliver
Oliver S. schrieb:> Wenn’s jetzt noch der nicht funktionierende Code wäre,
Den hat er ja noch nie gezeigt. Er hat nicht einmal gesagt, ob der Code
nicht funktioniert hat oder was falsch lief. Er hatte eigentlich nur
einen Breakpoint, der nicht gebreakt hat.
Mach F. schrieb:> Wenn ich einen Breakpoint im else setze, wird dieser nicht getriggert,> auch bei 0xFF oder eben -1 nicht.
Hab es reverted und beim Watch auf dez gestellt, rebuild all, jetzt
funktioniert auch dieser erste Code. Der einzige Unterschied zum init
Post war das Rebuild all...
Entschuldigt bitte all die Zeit die Ihr aufgewendet habt, aber eine
anregende Diskussion war es allemal. Schönen Abend allerseits
Mach F. schrieb:> Hab es reverted und beim Watch auf dez gestellt, rebuild all, jetzt> funktioniert auch dieser erste Code.
Das ist hoch anständig von Dir, dass Du es am Ende doch noch mal
versucht hast und das Ergebnis postest. Ich dachte schon, Du wärest mit
Deinen "Patchen" zufrieden. Aus sowas entsteht schnell Voodoo: Wenn
etwas nicht geht, dann obskure Verrenkungen weil "der Compiler spinnt".
Das gibt es natürlich auch, aber nicht bei O0 und trivialen Dingen. Und
wenn doch, sollte man erst Recht nicht flicken, bevor man den Fehler
isoliert und vom Hersteller bestätigt hat. Wenn man einfachen
Anweisungen nicht trauen kann, wie soll man jemals Fehler suchen.
A. S. schrieb:> Das ist hoch anständig von Dir, dass Du es am Ende doch noch mal> versucht hast und das Ergebnis postest. Ich dachte schon, Du wärest mit> Deinen "Patchen" zufrieden. Aus sowas entsteht schnell Voodoo: Wenn> etwas nicht geht, dann obskure Verrenkungen weil "der Compiler spinnt".
Das ist das Mindeste was ich tun sollte nachdem alle so viel Zeit damit
verbracht haben. Danke
Oliver S. schrieb:> (prx) A. K. schrieb:>> Das Verhalten müsste also bei IAR irgendwo dokumentiert sein.>> Indirekt ist es das in dem o.a. link:
Jein... Das implementation defined behavior des IAR Compilers ist im
"C/C++ Reference Guide" beschrieben.
Yalu X. schrieb:> Bei Michael wird er nicht hexadezimal, sondern dezimal und deswegen mit> Vorzeichen dargestellt. Ich schätze, dass man das Ausgabeformat im> Debugger irgendwo einstellen kann.
Der Debugger zeigt im Watch-Fenster per Default den Wert als ASCII + HEX
an. Über einen rechts-klick auf die Variable kann das Ganze dann
beispielsweise als "Dezimal" interpretiert werden. Über "Show As" sind
dann noch mehr Optionen möglich (siehe Screenshot).
Gruß,
Michael
Mach F. schrieb:> Der einzige Unterschied zum init> Post war das Rebuild all...
Hatte ich dir ja schon oben geschrieben, dass der IAR v8 da ein paar
üble Macken hat ;)
Auf einem SAM9G45 setzt der neue IAR8.x übrigens manchmal den Breakpoint
nicht wenn die CPU läuft.
Es hat sich nur der IAR von v7.x auf v8.3/8.5 geändert.
Gleicher J-Link, gleiches HW Target, gleicher PC, kein Win10 Update
zwischendurch.
Da haste eine main Schleife und weist zu 100%, dass der da durchläuft.
Setzt den Breakpointer, der kommt nicht.
Drückst beim IAR auf Pause und dann run -> Breakpoint kommt.
Ganz großes Kino!
Auf STM32 ist das bisher allerdings nicht passiert.
Da hat der IAR eine ganz andere Marotte!
Manchmal überspringt er Funktionen bei F11 (Step Into).
Passiert nur auf unseren STM32 Targets, auf dem dicken Cortex-A
passierts nicht.
Zudem hab ichs nur bei CPP Code mit virtual functions (Sprungtabelle)
erlebt.
Da verschluckt er sich wohl manchmal...
Mach F. schrieb:> Entschuldigt bitte all die Zeit die Ihr aufgewendet habt
Es hat ja vor allem viel Entwicklerzeit für die Firma gekostet, nämlich
deine.
Wenn das öfter vorkommt muss man mals Tooling überdenken ;)
@Michael F:
Was machen die rutschenden Breakpoints?
Da gabs im THread ja kein STatusupdate mehr von dir.
Mw E. schrieb:> Es hat ja vor allem viel Entwicklerzeit für die Firma gekostet, nämlich> deine.> Wenn das öfter vorkommt muss man mals Tooling überdenken ;)
korrekt, aber so ist es nun mal in der Entwicklung, wird nicht das erste
und nicht das letzte Mal so sein...
Mach F. schrieb:> korrekt, aber so ist es nun mal in der Entwicklung, wird nicht das erste> und nicht das letzte Mal so sein...
Na ja, das könnte dein Chef anders sehen. Der bezahlt dich für
Ergebnisse, nicht zum rumprobieren.
Oliver
Oliver S. schrieb:> Na ja, das könnte dein Chef anders sehen. Der bezahlt dich für> Ergebnisse, nicht zum rumprobieren.
genau so ist es, nur Ergebnisse zählen, aber jeder und jede die in der
Entwicklung arbeiten wissen auch, dass der Tag 24h hat und nicht immer
alles nach Plan läuft, zumindest habe ich das noch nie erlebt, wäre ja
auch langweilig... obwohl es zugegebenermassen ein wirklich sehr sehr
dummer "Bug" war aber das gibt es nun mal...
Schönen Abend noch
Mw E. schrieb:> Auf einem SAM9G45 setzt der neue IAR8.x übrigens manchmal den Breakpoint> nicht wenn die CPU läuft.> Es hat sich nur der IAR von v7.x auf v8.3/8.5 geändert.> Gleicher J-Link, gleiches HW Target, gleicher PC, kein Win10 Update> zwischendurch.Mw E. schrieb:> Manchmal überspringt er Funktionen bei F11 (Step Into).> Passiert nur auf unseren STM32 Targets, auf dem dicken Cortex-A> passierts nicht.> Zudem hab ichs nur bei CPP Code mit virtual functions (Sprungtabelle)> erlebt.
Gehe ich recht in der Annahme, dass Du zu beiden Themen Support-Requests
gestartet hast, damit die Probleme genauer untersucht werden können?
Mach F. schrieb:> obwohl es zugegebenermassen ein wirklich sehr sehr> dummer "Bug" war aber das gibt es nun mal...
Es wäre gut gewesen, gleich von Anfang an den erzeugten Assembler-Code
zu posten, da nun nicht mehr nachvollziehbar ist, was schief gelaufen
sein könnte...
Gruß,
Michael
Michael F. schrieb:> Es wäre gut gewesen, gleich von Anfang an den erzeugten Assembler-Code> zu posten, da nun nicht mehr nachvollziehbar ist, was schief gelaufen> sein könnte...
Klar, soll auch keine Kritik sein sondern eher auf mich selbst bezogen,
rebuild all hätte mir auch selbst einfallen können.
Danke