C unerklärliches Programmverhalten

OP #4053503
Lesenswert?
• ▲
▼
Ich wollte unechtes multitasking in c mithilfe eines Timers und einem 
Signalhandler unter Linux Implementieren, um es später auf einen uC mit 
Timerinterrupt zu portieren.

Aber das Programm tut etwas, das da einfach nicht steht:
1
    if(num_running_threads>=MAX_THREADS)
2
      goto add_thread_failture_maxthreads_exceeded;
3
    for(int current_thread=MAX_THREADS;current_thread--;){
4
      printf("create_thread %d %s\n", current_thread, threads[current_thread].active?"active":"inactive");
5
      if(!threads[current_thread].active)
6
        break;
7
    }
8
    num_running_threads++;
9
    printf("create_thread %d %d\n",num_running_threads, current_thread);

Führt irgendwie zur Ausgabe von:
1
save_current_thread 0
2
create_thread 7 inactive
3
create_thread 1 0
4
save_current_thread 0
5
continue_current_thread 0
6
save_current_thread 0
7
continue_current_thread 0
8
save_current_thread 0
9
continue_current_thread 0
10
save_current_thread 0

Und das verstehe ich nicht, diese Zeile:
1
create_thread 7 inactive
2
create_thread 1 0
Sollte so Aussehen:
1
create_thread 7 inactive
2
create_thread 1 7

Was könnte hier Passiert sein?

Komplettes Programm ist im Anhang.

Ausfgeführt hab ich das so:
1
gcc -std=c99 -Wall -Wextra -pedantic isr_timerbased_task_sheduler.c -o isr_timerbased_task_sheduler
2
./isr_timerbased_task_sheduler>log.txt&sleep 0.1;kill $!;head log.txt;
System:
1
Linux Server1-hp 3.13.0-32-generic #57-Ubuntu SMP Tue Jul 15 03:51:08 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
Compiler:
1
gcc (Ubuntu 4.9.2-0ubuntu1~14.04) 4.9.2
2
Copyright (C) 2014 Free Software Foundation, Inc.
3
This is free software; see the source for copying conditions.  There is NO
4
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Angehängte Dateien:
OP #4053541
Lesenswert?
• ▲
▼
Peter II schrieb:
> was soll der mist mit den gotos?

Ich fand es schöner die Einzelnen Programmteile mit labeln zu 
beschriften, als grosse unübersichtliche verschachtelte if und switch 
strukturen zu verwenden. Die gotos erfüllen ihren zweck.

Ich hab diesen Fehler gerade gefunden:
1
for(int current_thread=MAX_THREADS;current_thread--;){
Muss natürlich so sein:
1
for(current_thread=MAX_THREADS;current_thread--;){

Jetzt bekomme ich aber einen SIGSEGV, hoffentlich sind setjmp und 
longjmp überhaupt auf diese weise Anwendbar...
Gast #4053543
Lesenswert?
• ▲
▼
Daniel A. schrieb:
> Peter II schrieb:
>> was soll der mist mit den gotos?
>
> Ich fand es schöner die Einzelnen Programmteile mit labeln zu
> beschriften, als grosse unübersichtliche verschachtelte if und switch
> strukturen zu verwenden. Die gotos erfüllen ihren zweck.

Wenn du den Programmfluss verschleiern willst nur zu.
Gast #4053558
Lesenswert?
• ▲
▼
TriHexagon schrieb:
> Wenn du den Programmfluss verschleiern willst nur zu.

Wer keine Ahnung vom Programmieren hat, der kann sich mit gotos 
natürlich übel seinen Code verunstalten. Es gibt aber Situationen, in 
dene gotos durchaus übersichtlicher sind, und dann ist es auch sinnvoll, 
diese einzusetzen. Mir ist nicht klar, was das mit verschleiern zu tun 
hat - im Gegenteil.
Gast #4053584
Lesenswert?
• ▲
▼
radiostar schrieb:
> TriHexagon schrieb:
>> Wenn du den Programmfluss verschleiern willst nur zu.
>
> Wer keine Ahnung vom Programmieren hat, der kann sich mit gotos
> natürlich übel seinen Code verunstalten. Es gibt aber Situationen, in
> dene gotos durchaus übersichtlicher sind, und dann ist es auch sinnvoll,
> diese einzusetzen. Mir ist nicht klar, was das mit verschleiern zu tun
> hat - im Gegenteil.

Wenn man strukturiert in C programmiert, dann werden die Anweisungen 
standardmäßig von oben nach unten ausgeführt. Ausnahme sind höchstens 
Schleifen und Funktionen/Prozeduren. Bei der richtigen Einrückung hat 
man dann noch quasi visuell den Programmablauf im Auge und kann einzelne 
Abschnitte wie Schleifen einfach überspringen. Bei deinem gotos springst 
du mal nach unten, mal nach oben und man muss ständig nach Labels 
suchen. Das ist wie bei einem Buch in dem man sich ständig Verweise 
anschauen muss, was den Lesefluss absolut abträglich ist.

Es gibt Fälle in dem Gotos angebracht sind, doch hier sehe ich keine.
OP #4053593
Lesenswert?
• ▲
▼
c-liker schrieb:
> Peter II schrieb:
>> wenn man Funktionen beschreiben will, dann verwenden man
>> Prozeduren/Funktionen und nicht Labels.
> und nicht zu vergessen Kommentare.

Ok, ich werde mir sowieso einen neuen Ansatz überlegen müssen, und dass 
Programm nochmal neu schreiben.

Es scheint folgendes zu passieren:
 1) main
 2) timer stackframe speichern
 3) funktion threadX aufrufen
 4) timer stackframe speichern
 5) timer stackframe nach main widerherstellen
 6) timer verlassen, zu main zurückkehren
 7) timer stackframe speichern
 8) timer stackframe nach timerX widerherstellen
    -> Zerstört stäck weil:
      * main
      * 1. stackframe timer <-- ist bereits zurückgekehrt, alles 
folgende existiert nichtmehr auf dem stack
      * timerX
      * 2. stackframe <-- widerherstellung zerstört den stack

Passt auch zur ausgabe von valgrind (im Anhang)
Angehängte Dateien:
Gast #4053608
Lesenswert?
• ▲
▼
Daniel A. schrieb:
> TestTriHexagon schrieb:
>> Bei deinem gotos springst
>> du mal nach unten, mal nach oben
>
> Dan hast du meinen Code nicht sehr genau Angeschaut, Da springe ich
> immer von oben nach unten, aber nie von unten nach oben.

Mhm hab noch mal drüber geschaut, hätte schwören können das es einen 
Sprung nach oben gab. Na egal.

Wie Peter schon anmerkte sind Funktionen anstatt der Labels besser 
geeignet. Aber das musst du wissen.
Gast #4053638
Lesenswert?
• ▲
▼
Für preemptive braucht man je Task einen eigenen Stack. Und etwas ASM um 
ein setjump/longjump mit Stack-Umschaltung auf der jeweiligen Plattform 
zu implementieren. Und unter Linux könnte es sein, daß der Stack nicht 
beliebig auf dem Heap liegen darf, aber dazu könnte man die Task-Stacks 
als lokale Variablen in main() definieren. Ob man dabei was lernt, das 
auf dem μC weiterhilft? Who knows?
OP #4053718
Lesenswert?
• ▲
▼
Oliver S. schrieb:
> Um mal aufs ursprüngliche Problem zurückzukommen: Zähl mal nach, wie
> viele Variablen namens current_thread es in deinem Programm gibt...

Die überzälige lokale variable habe ich bereits bemerkt:

Daniel A. schrieb:
> Ich hab diesen Fehler gerade gefunden:
1
for(int current_thread=MAX_THREADS;current_thread--;){
> Muss natürlich so sein:
1
for(current_thread=MAX_THREADS;current_thread--;){

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