Programme beenden!

Gast #1570359
Lesenswert?

Hallo!!!
Kann mir einer sagen ob ich irgendwann mal ein Problem mit dem AVR 
kriegen werde wenn ich meine Programme so schreibe:


void prog1()
{
prog2();
...
...

}

void prog2()
{
prog3();
...
}

void prog3()
{
prog1();
...
.
..
}

weil die werden ja schließlich nicht richtig beendet oder?
Gast #1570366
Lesenswert?

Das Problem, das du da vollkommen richtig erkannt hast, ist die endlose 
Rekursion. Bei jedem Aufruf eines Unterprogramms landet mindestens eine 
Adresse auf dem Stack, um nach Beendigung des Unterprogramms wieder dort 
weitermachen zu können, wo vor Eintritt in das Unterprogramm aufgehört 
wurde.
Irgendwann reicht der Speicher nicht mehr für weitere Adressen.
#1570377
Lesenswert?

Du kannst ruhig sowas schreiben (obwohl es vollkommen sinnfrei ist).
Schlimm wird es erst, wenn Du eines davon im Main aufrufst.

Wenn man schon Rekursionen macht, dann nur über eine Funktion. Ansonsten 
verliert man ruckzuck den Überblick, wo und wann nun die Endebedingung 
der Rekursion ausgeführt wird.


Peter
Gast #1570396
Lesenswert?

Danke für die schnellen Antworten. Und wenn ich es so schreibe, dann ist 
es richtig? oder?

void prog1()
{
prog2();
...
...

}

int prog2()
{
if prog3()==1
return 1
else
weiter
...
}

int prog3()
{
prog1();
...
.
return 1
}
#1570398
Lesenswert?

Thomas Burkhart schrieb:
> Da es zum Titel passt:
>
> Was macht ein AVR eigentlich wenn er am Ende von main() angekommen ist?

Der C-Standard schweigt sich darüber aus, was dann passieren muss.

Beim gcc ist es so, dass der Code, der main() aufruft in eine 
Endlosschleife eintritt sobald main retourniert. Wenn mich nicht alles 
täuscht, werden dabei Interrupts sogar abgeschaltet.
#1570404
Lesenswert?

> Beim gcc ist es so, dass der Code, der main() aufruft in eine
> Endlosschleife eintritt. Wenn mich nicht alles täuscht, werden dabei
> Interrupts sogar abgeschaltet.

Ja, nach main wird _exit aufgerufen. Und die Default-Implementierung von 
_exit in der AVR-Libc enthält ein cli und eine Endlosschleife.
#1570415
Lesenswert?

Anfänger schrieb:
> Danke für die schnellen Antworten. Und wenn ich es so schreibe, dann ist
> es richtig? oder?

Es ist immer noch vollkommener Schwachfug.
Du hast überhaupt nicht darüber nachgedacht, was da passiert.
Und Du hast vermutlich auch nicht die geringste Vorstellung, was Du 
eigentlich willst.

Schalte bitte den PC aus, nimm Papier und Bleistift und male einen 
Programmablaufplan auf. Wenn der dann irgendwas sinnvolles tut, kannst 
Du den PC wieder einschalten.


Peter
Gast #1570430
Lesenswert?

> Peter schrieb:
> > ich denke nicht, ist doch auch eine entlosschleife

> Ja, aber die werden doch dann richtig beendet. und dann gibt es keinen
> speicherüberlauf. Wie ich es verstehe.

wo wird denn etwas beendet?
#1570447
Lesenswert?

Anfänger schrieb:
> Ja, aber die werden doch dann richtig beendet. und dann gibt es keinen
> speicherüberlauf. Wie ich es verstehe.

Quatsch. Alles hinter dem unbedingten Aufruf einer Rekursion ist toter 
Code.
Das Ende wird nie erreicht!

Eine Rekursion muß immer eine Abbruchbedingung haben!
Deshalb sollten Anfänger erst garkeine Rekursionen schreiben.


Peter
Gast #1570451
Lesenswert?

Peter Dannegger schrieb:
> Es ist immer noch vollkommener Schwachfug.
> Du hast überhaupt nicht darüber nachgedacht, was da passiert.
> Und Du hast vermutlich auch nicht die geringste Vorstellung, was Du
> eigentlich willst.

Tut mir leid:
doch ich hab ein kleines Programm mit einem TSIC Temperatursensor und 
einem LCD-Display. Und das sieht halt so aus es funktioniert zwar aber 
ich hatte halt meine bedenken ob es auf dauer funktioniert.

main()

initialisierungen

while()
{
menü();
}

über das menü kann ich die temperaturanzeige aufrufen.

menü
{
taste1 >> Anzeige();
einstellungen();
anzeige von einstellungen();
}


und nach ca. 10 sekunden wechselt mein programm in ein stromsparmodus 
ohne LCD

Anzeige()
{
10sek warten;
Anzeige ohne lcd();
"if anzeige ohne lcd == 1
dann menü
nein dann weiter."
}

und von der anzeige ohne lcd gelange ich durch drücken von taster1 in 
das menü();

anzeige ohne lcd
{
taster1 >> menü();
"return 1;"
taster2 >> anzeige();
"return 0;"
}

Mein programm ist ohne returns.
Und das ist ja eine schlechte methode wie man es mir am anfang vom 
thread erklärt hatte.

ich werde es halt mit "return" machen.
#1570466
Lesenswert?

Peter Dannegger schrieb:
> Eine Rekursion muß immer eine Abbruchbedingung haben!
> Deshalb sollten Anfänger erst garkeine Rekursionen schreiben.
>

Um Rekursion zu verstehen muss man Rekursion verstehen ;-) Aber dann 
bitte am Computer wo man schön grafisch (bzw. per Text) verfolgen kann 
was überhaupt passiert. Ich finde grad Anfänger sollten ein paar 
Rekursionsfunktionen testhalber schreiben und verstehen weil es ein 
wirklich grundlegendes Konzept ist und man auch verstehen kann was im 
Hintergrund passiert (bei iterativen Funktionen verschwendet doch keiner 
nen Gedanken an die Rücksprungadresse bzw.den Stack). Aber wenn man 
sowas testet dann wie schon erwähnt nicht am µC.
#1570470
Lesenswert?

Anfänger schrieb:

> und von der anzeige ohne lcd gelange ich durch drücken von taster1 in
> das menü();

Ich dachte mir schon, dass es wohl so etwas wie eine Menüsteuerung wird.

>
> anzeige ohne lcd
> {
> taster1 >> menü();
> "return 1;"
> taster2 >> anzeige();
> "return 0;"
> }

Nein. das machst du nicht so.
Die Funktion "anzeige ohne lcd" liefert einen returncode, der dem 
Aufrufer mitteilt, wi es weiter geht. Der Aufrufer wertet den Code aus 
und entscheidet anhand dessen, was er weiter tun will. Das kann 
natürlich zb auch bedeuten, dass er selbst wieder einen Return Code an 
seinen Aufrufer übergibt, bis man dann irgendwann wieder in main() in 
der while Schleife zurück ist.
Moderator Persönliche Seite #1570497
Lesenswert?

Karl heinz Buchegger schrieb:

>> Was macht ein AVR eigentlich wenn er am Ende von main() angekommen ist?
>
> Der C-Standard schweigt sich darüber aus, was dann passieren muss.

Nicht ganz exakt: der Standard sagt, dass mit dem Rückkehrwert von
main() die Funktion exit() gerufen wird.  Von dieser wird dann
implizit erwartet, dass sie in der Lage ist, das Programm auf
irgendeine Weise zu beenden.

Die Default-Implementierung von exit() erledigt dann die von dir
beschriebene Endlosschleife, wobei die Applikation allerdings auch
ihr eigenes exit() liefern kann.

Streng genommen schreibt der Standard diese Vorgehensweise nur für
eine `hosted application' vor, aber in diesem Modus wird der GCC in
der Regel auch auf einem Controller betrieben, da er ja auch auf
eine Standardbibliothek zurückgreift.
Gast #1570530
Lesenswert?

cool danke, dann wäre das problem ja gegessen. weil ich eigentlich die 
heizung von meinem aquarium steuern möchte. will ich das es auch nach 
einem jahr funktioniert. und die eingestellten werte sind sowieso 
nachdem reset im eeprom gespeichert.
Schönen Tag noch und danke für eure hilfe.
Gast #1570534
Lesenswert?

Nachtag:

bin ja gespannt wo du in deiner "kaum vorhanden" Struktur den reset vom 
Watchdog einbaust. Ausdem wenn dein Stack überläuft ist das Verhalten 
vom Programm nicht mehr definiert, es kann auch passieren das du die 
armen kleinen Fische kochst.

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