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
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.
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.
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
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.
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
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 |
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).
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.
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.