Forum: Mikrocontroller und Digitale Elektronik ATMEGA32 Stackauslastung im AVR Studio anzeigen


von Bernhard N. (bernieserver)


Lesenswert?

Hallo,

ich habe mal eine ganz allgemeine Frage:

Wann weiß ich, dass beim Programmieren der Stack des Atmels überläuft? 
Lässt sich das überhaupt vorhersehen oder muss ich der RAM 
Nutzungsangabe des Compilers vertrauen? Gibt es eine Maximalgrenze, wo 
der Atmel aussteigt oder "crasht" der Stack dann einfach in dem 
Datenbereich hinein und manipuliert darin herum?

Den Heap (malloc... ) nutze ich nicht.

Ich nutze AVR Studio zum Debuggen und nutze einen "MK2" - Debuggerclon.



Gruß
Bernhard

von Ben _. (burning_silicon)


Lesenswert?

im prinzip kannst du jederzeit den stackpointer auslesen, dann weißt du 
auch wieviel auf dem stack liegt.

bei PCs kann man das so machen, daß man den speicherbereich mit einem 
bestimmten bitmuster füllt, das zu prüfende programm dann etliche tage 
und/oder unter den fraglichen bedingungen testet und dann schaut bis 
wohin das vorher gelegte bitmuster zerstört wurde. damit weiß man auch 
wie voll der stack war.

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


Lesenswert?

Ben _ schrieb:
> bei PCs kann man das so machen, daß man den speicherbereich mit einem
> bestimmten bitmuster füllt

Bei PCs kann man das mittlerweile eher nicht mehr so machen, weil
der Stack dank virtual memory dynamisch nach Bedarf immer weiter
wächst. ;-)  Aber bei einem Controller kann man das auf jeden Fall
so machen.

von Bernhard N. (bernieserver)


Lesenswert?

Danke,

nur hört sich das alles etwas kompliziert an. Wird der Stackpointer 
nirgends mitgeloggt? Oder ist die Wahrscheinlichkeit einfach so gering 
dass das nicht auftritt?
Wie siehts mit der Stacksize aus?

Gruß


Bernhard

von aaaa (Gast)


Lesenswert?

Wahrscheinlichkeit dass es auftritt? Die ist bei jedem Programm anders. 
Grundsätzlich sollte man es aber als potentiell möglich ansehen, dass es 
unter bestimmten Bedingungen mal vorkommen kann.
Wenn du viele verschachtelte Funktionsaufrufe hast die jedes mal viele 
Register sichern müssen bekommst du schneller Probleme.

Eine Idee für dich: Nimm nen Counter und lese bei jedem Counterüberlauf 
den Wert des SPs aus. Den geringsten(!) Wert speicherst du dann irgendwo 
hin.

von Peter (Gast)


Lesenswert?

Jörg Wunsch schrieb:
> Bei PCs kann man das mittlerweile eher nicht mehr so machen, weil
> der Stack dank virtual memory dynamisch nach Bedarf immer weiter
> wächst. ;-)  Aber bei einem Controller kann man das auf jeden Fall
> so machen.

scheinbar doch

http://www.pro-linux.de/news/1/16058/alte-sicherheitsluecke-im-kernel-geschlossen.html

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


Lesenswert?

Peter schrieb:

> scheinbar doch
>
> 
http://www.pro-linux.de/news/1/16058/alte-sicherheitsluecke-im-kernel-geschlossen.html

Das ist (abgesehen davon, dass es ein Bug war -- sowas sollte
natürlich nicht passieren) doch aber was komplett anderes
als der Versuch, den "ganzen" Stack vorab mit einem Muster zu
beschreiben um danach festzustellen, wie viel davon wirklich
genutzt worden ist.  (Davon abgesehen werden die stack pages dort
vom OS vermutlich wirklich mit Nullen vorbelegt als Maßnahme dagegen,
dass möglicherweise sensitive Informationen eines anderen Prozesses,
dem dieser Speicher früher mal gehört hat, plötzlich zugänglich
werden.)

Normalerweise gibt's beim Versuch, den "ganzen" Stack zu belegen,
irgendwann ein SIGSEGV:
1
$ cat foo.c
2
int recurse(int i)
3
{
4
  return recurse(i * 2);
5
}
6
7
int
8
main(void)
9
{
10
  return recurse(42);
11
}
12
$ cc -O -o foo foo.c
13
$ ./foo
14
Segmentation fault

von Ben _. (burning_silicon)


Lesenswert?

naja ist ne alte technik. gaaanz früher zu DOS-zeiten (das hieß auch mal 
was anderes als denial of service) war der stack maximal 64kbyte groß 
(ein 16bit segment) und man war bestrebt möglichst wenig speicher zu 
reservieren. es macht keinen sinn speicher zu reservieren, den man nicht 
braucht - vor allem bei der TSR- (terminate and stay resident) oder 
virenprogrammierung (im grunde technisch nichts anderes als ein TSR). 
TSR-programme nutzen nach dem start z.b. den stack anderer programme. 
deshalb stack nur so groß wie nötig, und da war das eine beliebte 
methode um festzustellen ob man den reservierten stack wirklich braucht 
oder ob man noch weniger speicher für ihn reservieren kann.

klar, heute gibts bei PCs speicher für den stack im überfluss, und dank 
flat-speichermodell kümmert sich auch niemand mehr um die segmentierung.

trotzdem find ich das verfahren bei µCs vielleicht noch brauchbar, 
obwohl man dort den stack wohl immer ganz ans ende des RAM packt und ihm 
somit sämtlicher ungenutzter speicher zur verfügung steht. die größe 
spielt also eine untergeordnete rolle, wohl aber wenn ich in einer 
beliebigen umgebung rausfinden will wie groß der stack wird. dann würde 
ich das genau so machen weil ich die umgebung dafür nicht zu kennen 
brauche. beim start RAM komplett mit z.b. 88h füllen und irgendwann 
abzählen wo das letzte 88h im RAM steht. RAM-größe minus diese position 
ergibt die maximale stackgröße (wenn nicht gerade wer eine 88h auf den 
stack geschmissen hat, deswegen noch ein paar byte sicherheit lassen).

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


Lesenswert?

Ben _ schrieb:
> naja ist ne alte technik. gaaanz früher zu DOS-zeiten (das hieß auch mal
> was anderes als denial of service)

[OT]

Nö, hieß es damals schon. ;-)
1
   char *cp = NULL;
2
3
   [...]
4
   *cp = mychar;

...und der "denial of service" war perfekt.  Dann half nur noch der
Resetknopf.

von sudo (Gast)


Angehängte Dateien:

Lesenswert?

Um zum Thema zurückzukommen, hier zwei Files die das gewünschte 
nachrüsten.

Einfach mitcompilieren, im Programm kann man sich dann per 
get_mem_unused() den "unberührten" Teil des Stacks ausgeben lassen.

Weis leider nicht mehr von wen der Code ursprünglich stammt, vermute die 
Codesammlung hier.

von Ben _. (burning_silicon)


Lesenswert?

naja kaputt bekommt man alles wenn man will. zur not das erste kbyte des 
RAM schrotten, damit war die interrupttabelle weg und ende. und es gab 
auch irgendeinen befehl mit dem sich die console nach null umleiten 
ließ, das war's dann auch.

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.