Variable innerhalb eines Threads ändern

OP #7542216
Lesenswert?

Hallo,

Habe ein kleines Problem...

Ich habe folgenden Simplen Code:

1
uint8_t refVal = 0;
2
bool isRailConnected = false;
3

4
void i2c_commTask(void *argument)
5
{
6
 for(;;)
7
 {
8
   if(!isRailConnected)
9
   {
10
       isRailConnected = true;
11
       refVal = 1;
12
   }
13
   vTaskDelay(1);
14
 }
15
}

Nun wird zwar bis zum nächsten Durchlauf "isRailConnected" auf true gesetzt, aber beim nächsten Durchlauf der for schleife ist "isRailConnected" wieder auf false und refVal = 0....

Was muss ich tun, um aus dem gestarteten Thread die Variablen außerhalb zu ändern?

Das ganze läuft auf einem STM32F407VET6 und C++....

vielen Dank, Daniel

#7542256
Lesenswert?

uint8_t refVal = 0; bool isRailConnected = false;

uint8 und bool und noch vermutlich verschiedene Contexte. Da würde ich aufpassen. Denn STM32 ist ja 32 bit weit. Wenn der Compiler den uint8 und den bool dann in eine 32 bit RAM unterbringt dann wird nicht immer bei read modify write zufriffen richtig funktionieren.

Also bei Verschidene Contexten (main, isr, task) dann gucken das Variablen die über contexte hinweg gehen, am besten immer den intrinsic bitweite haben. Also hier 32 bit.

Dann sollte man prinzipiell gucken, dass der Compiler am besten hier auch nicht optimiert und die uint8 variablen in 4er Pakete zusammenpackt.

OP #7542260
Lesenswert?

Sonst würde ich nicht fragen :-) Die Variablen werden einmal in der main.cpp so definiert und durch nichts anderes beschrieben.

"isRailConnected" nimmt immer wieder den "default" "false" wert ein, obwohl er im Thread auf "true" gesetzt wurde. Beim Debuggen kann ich klar sehen, bis zum Ende der for schleife ist die Variable auf "true" wie gesetzt.

Beginnt die for(;;) von vorne, ist der Wert plötzlich wieder "false"...

#7542307
Lesenswert?

In C gibt es _Atomic und funktionen wie atomic_compare_exchange_strong in der stdatomic.h. C++ hat std::atomic<T>. Ob die auf deiner Platform verfügbar sind, weiss ich aber nicht.

Ich würde sowas zwar auch anders lösen. z.B. eine Task Queue und ein Thread Pool mit Workern, die die Tasks abarbeiten wenn sie gebraucht werden. Oder jenachdem würde ich Green Threads statt echte, oder eine Kombination davon, nehmen.

#7542355
Lesenswert?

Daniel S. schrieb:

"isRailConnected" nimmt immer wieder den "default" "false" wert ein, obwohl er im Thread auf "true" gesetzt wurde. Beim Debuggen kann ich klar sehen, bis zum Ende der for schleife ist die Variable auf "true" wie gesetzt.

Dann sind das Artefakte, weil Du mit Optimierung arbeitest und das alles wegoptimiert ist.

Printe die Variable z.B. in main aus, und Du wirst sehen, dass sie 1 wird und bleibt.

Persönliche Seite #7542383
Lesenswert?

J. S. schrieb:

Die Variable mal volatile deklarieren? Glaube zwar auch nicht das es das ist, und wenn es immer noch passiert wird die variable woanders überschrieben.

Das ist in Multithreading-Systemen nicht ausreichend.

Daniel S. schrieb:

Die Variablen werden einmal in der main.cpp so definiert und durch nichts anderes beschrieben.

Wenn die Variable nur in dem einen thread genutzt wird, muss das so funktionieren und du musst keine Vorkehrungen treffen. Da es ja eine globale Variable ist, kannst du im Debugger einfach einen Watchpoint drauf setzen und dann sehen wo sie wieder modifiziert wird. Vielleicht ist es ein wilder Pointer.

#7542387
Lesenswert?

Der gezeigte Code ist ja sicherlich nur ein Ausschnitt. Jede gute IDE kann die Referenzen von Variablen/Funktionen anzeigen, wurde darüber gesucht wer die Variable beschreibt? Liegen Arrays davor wo ein falscher Index eventuell böses treibt? Warnungen für implizite Funktionsaufrufe an und überprüft? Live View für Variable benutzt?

Moderator Persönliche Seite #7544698
Lesenswert?

Vermutlich tritt das Problem nur in einem größeren Kontext auf und nicht mit dem Minimalbeispiel. @TO: Ist meine Annahme richtig?

Ich tippe auf einen Bufferoverflow einer Variable, die oberhalb der gezeigten Vafiablendefinition ist.

Beispiel:

1
uint8_t buffer[16];
2
uint8_t refVal = 0;
3
bool isRailConnected = false;
4
...
5
buffer[16] = 0; // overwrite refVal

Der Code überschreibt höchstwahrscheinlich refVal mit 0 - kommt auf das Alignment an. Eventuell muss man hier den Index noch ein wenig rauf oder runterschieben...

Persönliche Seite #7547262
Lesenswert?

Jim M. schrieb:

Ansonsten schmeisst der Optimizer den Speicherzugriff zum Lesen raus, da sich die Variable im ihm zugänglichen Code Teil nicht geändert hat.

volatile ist kein Allheilmittel. Selbst wenn der Compiler den Variablenzugriff optimieren würde, sollte es innerhalb dieses Threads trotzdem konsistent funktionieren, was es nicht tut:

Daniel S. schrieb:

Beginnt die for(;;) von vorne, ist der Wert plötzlich wieder "false"...

Daniel S. schrieb:

Die Variablen werden einmal in der main.cpp so definiert und durch nichts anderes beschrieben.

Die Variable wird höchstwahrscheinlich durch einen wilden Pointer überschrieben. Das ist mit einem Watchpoint im Debugger in 3 Minuten gefunden.

#7551834
Lesenswert?

Niklas G. schrieb:

Die Variable wird höchstwahrscheinlich durch einen wilden Pointer überschrieben. Das ist mit einem Watchpoint im Debugger in 3 Minuten gefunden.

Ein simpler Stacküberlauf könnte auch dazu führen.

Man könnte die Variablen einfach "ganz woanders" anlegen, so daß sie woanders im Speicher liegen. Oder davor und danach jeweils ein Dummyarray anlegen, damit sich die Variablen im Speicher verschieben. Wenn sie dann "heile" bleiben, ist es wohl so ein Problem welches jetzt natürlich andere Daten überschreibt.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren