Forum: Compiler & IDEs Programme beenden!


von Anfänger (Gast)


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?

von Sven P. (Gast)


Lesenswert?

Ja, du kriegst ziemlich bald einen Stacküberlauf. Mach lieber mal ne 
Schleife draus.

von Peter (Gast)


Lesenswert?

ja weil dir nach ein paar (m)s der Stack überläuft und dein Speicher 
alle ist.

von Sven P. (Gast)


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.

von Peter D. (peda)


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

von Thomas B. (escamoteur)


Lesenswert?

Da es zum Titel passt:

Was macht ein AVR eigentlich wenn er am Ende von main() angekommen ist?

Gru´ß
Tom

von Anfänger (Gast)


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
}

von Karl H. (kbuchegg)


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.

von Karl H. (kbuchegg)


Lesenswert?

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

Nein.
Du hast nach wie vor das Problem, dass sich die Funktionen prog1, prog2 
und prog3 wechselseitig 'im Kreis' aufrufen.

(tm) Herr Kaiser: Ein Teufelskreis!

von Peter (Gast)


Lesenswert?

> Danke für die schnellen Antworten. Und wenn ich es so schreibe, dann ist
> es richtig? oder?
ich denke nicht, ist doch auch eine entlosschleife

von Stefan E. (sternst)


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.

von Anfänger (Gast)


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.

von Peter D. (peda)


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

von Peter (Gast)


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?

von Peter D. (peda)


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

von Anfänger (Gast)


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.

von Peter (Gast)


Lesenswert?

es geht nicht darum das keine "returns" vorhanden sind, es geht darum 
das du auch mal das Ende einer funktion erreichst. (Außer bei main 
sollte jede funktion auch mal beenden werden!)

von Martin Z. (zilluss)


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.

von Karl H. (kbuchegg)


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.

von klaus (Gast)


Lesenswert?

@Anfänger:

Beschreib doch mal was das Programm machen soll. Die Struktur so wie sie 
ist sieht extrem merkwürdig aus, das geht garantiert besser...

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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.

von Anfänger (Gast)


Lesenswert?

was ist eigentlich mit watchdogtimer? der ist doch dafür da, dass wenn 
sich der controller aufhängt. dann resetet wird.

von Peter (Gast)


Lesenswert?

ja

von Anfänger (Gast)


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.

von Peter (Gast)


Lesenswert?

Schreibe lieber ein saubere Programm und lerne etwas dabei.

von Peter (Gast)


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.

von Anfänger (Gast)


Lesenswert?

ich werd das programm noch überarbeiten

von Peter D. (peda)


Lesenswert?

Man baut ein Haus üblicher Weise nicht so, daß die Türen klemmen und man 
es nur über den Notausgang verlassen kann.

Während der Entwicklung hat der Watchdog grundsätzlich aus zu bleiben, 
damit man seine Fehler auch sieht.


Peter

von Anfänger (Gast)


Lesenswert?

ich werde jetzt mein menu in eine while-schleife schreiben und von dort 
aus meine verschiedene funktionen aufrufen. hab ich aus diesem beitrag: 
Beitrag "Menü (hängt)" und dann muss es doch 
funktionieren.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.