Mathias hat geschrieben:Zufällig war der Speicherbereich frei, ansonsten hättest eine SIGSEV gehabt.
Zufällig ist es nicht ganz, er befindet sich ganz oben auf dem Stack (welcher nach oben wächst) was also bedeutet, wenn er nach oben über den array schreibt müsste er schon über alle Stackframes drüber schreiben bis es zu einer Zugriffsverletzung kommt, und der stack ist in produktiven programmen für gewöhnlich recht groß. Daher ist es recht unwahrscheinlich bei Stack-Arrays eine Zugriffsverletzung zu bekommen.
Erwin hat geschrieben:af0815, darf ich aus Deiner Aussage entnehmen, dass standardmäßig der Debugger fast ausgeschaltet ist?
Nein standardmäßig ist praktisch die minimale funktionalität gegeben um den GDB zu verwenden. Für kleinere sachen ausreichend, für größere Projekte würde ich einfach die Default Build-Modes Debug und Release verwenden.
kupferstecher hat geschrieben:Die Stacküberprüfung heißt - soviel ich weiß - dass das Programm regelmäßig schaut, ob der Stack noch in seinen zugewießenen Speicherbereich passt. Ist das nicht der Fall und gibt es keine Überprüfung, so wird er einfach über andere Speicherbereiche "drüberbügeln" oder das Betriebssystem antwortet mit einer Zugriffsverletzung. Die regelmäßigen Überprüfungen brauchen auch Rechenzeit und im produktiven Einsatz ist das Resultat oft das gleiche: Das Programm stürzt ab (Bzw. wird von der Überprüfungfunktion terminiert/abgeschossen).
Bist du dir da sicher? denn die Stack Limits werden afaik vom Betriebsystem enforced (z.b. unter linux in der limits Datei), zwar muss das OS kein limit haben (z.b. linux: ulimit -s unlimited), aber normalerweise ist ein Limit eingestellt. Daher wäre diese Option in den Meißten fällen nutzlos, und damit nur Laufzeitverschwendung. Ich hab da aber keine ahnung was diese Option macht.
Erwin hat geschrieben:Bei Assertions geht es um Dokumentation des Quelltextes? Das allein hört sich schon für mich verwirrend an. Danke für die Vorwarnung.
Assertions sind debug code die ein Verboses Failen verursachen. z.B. assert(x1>x2 , 'X1 needs to be bigger than x2'). Wenn die Assertion failed, dann crasht dein programm mit der Message die angegeben wurde (Denn ein Crash + Message ist normalerweise immer besser als wenn der PC still den fehler schluckt und einfach weitermacht mit eventuell falschen daten). Im release code deaktivierst du dann assertions, damit werden diese nicht ausgeführt um Leistung zu sparen, und Verbose Fehlermeldungen zu unterdrücken (mit denen der Endnutzer meist nichts anfangen kann). Immer wenn du irgendwelche annahmen machst (z.B. das argument muss >= 0 sein oder so) solltest du diese als assertions einbauen. Das führt dazu das wenn du irgendwann dein programm änderst, du nicht vergisst das diese annahmen (so genannte invarianten) noch gelten. Wenn du stattdessen dir denkst, "ich ruf das eh immer >= 0 auf, also brauch ich keine abfgrage" kracht es spätestens wenn du nach 6 monaten mal ein update machst, und das schonwieder komplett vergessen hast.
Assertions sind aber aussschließlich zum Debuggen für entwickler gedacht, und sollten im produktiven Code nicht drin sein
Erwin hat geschrieben:Ok, hätte ich mir teils auch denken können, dass man das deaktiviert hat wegen der Geschwindigkeit.
Normalerweise macht man sich bei den meisten Programmen keine Gedanken über die Vor-Einstellungen. Nur dann, wenn was nicht passt, was meist erst dann der Fall ist, wenn ich etwas anders als die Meisten es machen will.
Die setzen also auf Schnelligkeit, statt Gründlichkeit? Naja, je nach dem, ... kann das ein oder andere Angenehmer sein. Aber wäre schön, wenn man über diese Infos einfacher und schneller mit stolpern würde, also mitgeteilt bekäme. Weil dann weiß man auch, in dem Fall hier, dass man da ein wenig selbst kontrollieren muss. Also in dem man dann vor dem Finale überall (?) einen Hacken rein macht, und beim Final (wegen Programmgröße?) dann wieder raus nimmt. Stattdessen scheinen die Infos irgendwo versteckt zu sein?
Lazarus kann dir den Standard Release und Debug Modus per klick erstellen, die haben ziemlich gute voreinstellungen: Projekteinstellungen->Compilereinstellungen, oben Erstellmodi haken setzten, auf den ... button clicken und dann auf Debug Und Release Modus erstellen klicken. Den Default modus kannst du dann löschen.
Über die Dropdown box kannst du dann den aktiven modus wählen
Erwin hat geschrieben:Geht schon los ... . Nach dem was ich auf Wikipedia gelesen habe, muss es während der nutzung nicht zum Überlauf kommen, aber ein Angreifer kann dies verursachen. Auch sonst, wenn ich das richtig verstanden haben, kann im Falle eines Stack (Speicher?) überlauf wegen doppelter (?) Belegung von Platz (?) zu gravierenden Datenverlust bis hin zum Schaden an dem Programm selbst (?) kommen. Also ein ganz Gefährliche Sache?
Wie gesagt in den meißten fällen wird dir das Betriebsystem nicht genug speicher zur Verfügung stellen damit du überhaupt eine so genannte heap collision (stack der nach oben wächst und heap der nach unten wächst überschneiden sich) bekommen kannst. Man muss schon aktiv, mit administratorrechten das bei seinem Betriebsystem einstellen damit man da was kaputt machen kann.
Das hauptproblem für eine Stacküberlauf sind aber auch keine angreifer, sondern dumme programmierer. z.B funktionen mit großem stack:
Code: Alles auswählen
procedure SomeRecursiveProcWithVeryLargeStack(i: Cardinal);
var arr: array[0..1000000] of Byte; // 1MB stack size
begin
if LongBool(i) then SomeRecursiveProcWithVeryLargeStack(i-1);
end;
Ein entsprechend großes i würde dir damit eine heap collisiob geben. Aber, mit dynamischen arrays oder pointer auf statische arrays und new-dispose, wäre das ganze kein problem
Hm... vielleicht sollte ich extra Thread zu den Einstellungen aufmachen ... falls es den doch nicht schon gibt?
Es bräuchte einfach eine vernünftige Wikiseite die
alles wenigstens kurz erklärt (und vor allem alles auf einer Seite)
Mathias hat geschrieben:Ich finde es gut, das es per Default deaktiviert ist. Wegen mir könnte man auch den Debugger deaktivieren. Da kommen sowieso im nur Fragen bei Anfängern, wieso die EXE so aufgebläht ist.
Wen jemand fortgeschritten ist, und weis wie das Debugging funktioniert, dann weis er auch wo man es einschaltet.
Das ding ist das es generell zum debugging nicht sonderlich viele informationen gibt. Am anfang hab ich 90% der zeit mit WriteLn und ShowMessage gedebuggt, weil ich das Variablen überprüfen feature nicht kannte.
Zum debuggen generell,
Für etwas verbosere ausgaben und praktisch alle memory checks die man sich vorstellen kann, kann man unter Linux auch Valgrind verwenden. Das ganze hat nen heftigen overhead (faktor 100 langsamer mindestens), bietet dir aber eine vielzahl an tools um sehr wiederliche fehler zu finden. Das übernimmt praktisch die aufgabe von Heaptrc, rangechecks und vielem mehr. Aber meißt sollten die FPC features und der GDB bereits schon reichen und schneller sein.
Valgrind erstellt ein sog. shadow memory modell, was praktisch für jede Memory location zusätzliche informationen bereitstellt, um somit extrem akkurate tests durchzuführen.