www.mikrocontroller.net

Forum: Compiler & IDEs Programme beenden!


Autor: Anfänger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Sven P. (haku) Benutzerseite
Datum:

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

Autor: Peter (Gast)
Datum:

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

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Thomas Burkhart (escamoteur)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da es zum Titel passt:

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

Gru´ß
Tom

Autor: Anfänger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Anfänger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Anfänger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!)

Autor: Martin Z. (zilluss)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Anfänger (Gast)
Datum:

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

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja

Autor: Anfänger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schreibe lieber ein saubere Programm und lerne etwas dabei.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Anfänger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich werd das programm noch überarbeiten

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Anfänger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.