Kleines Crash-Quiz

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Straightdog
Beiträge: 10
Registriert: Mo 1. Aug 2011, 18:52

Kleines Crash-Quiz

Beitrag von Straightdog »

Aufgabe: Bringt das folgende Programm zum Absturz.
Einschränkung: Ihr dürft nichts hinzufügen, sondern nur etwas entfernen. Und zwar genau 3 Zeichen.

Code: Alles auswählen

program Sphynx;
 
{$mode objfpc}{$H+}
 
type
 
  { TMyClass }
 
  TMyClass = class
  private
    FField: string;
    function GetFField: string;
    procedure SetFField(const s: string);
  public
    procedure Clear; virtual;
    procedure doSomething(const s: string); virtual;
    property Field: string read GetFField write SetFField;
  end;
 
{ TMyClass }
 
function TMyClass.GetFField: string;
begin
  Result := FField;
end;
 
procedure TMyClass.SetFField(const s: string);
begin
  FField := s;
end;
 
procedure TMyClass.Clear;
begin
  FField := '';
end;
 
procedure TMyClass.doSomething(const s: string);
begin
  Clear;
  Field := s + s;
end;
 
var
  m: TMyClass;
  s: string;
 
begin
 
  m := TMyClass.Create;
  m.doSomething('Test');
  WriteLn('"' + m.Field + '"');
  m.doSomething(m.Field);
  WriteLn('"' + m.Field + '"');
  WriteLn('');
  WriteLn('Hit return key to end the program');
  ReadLn(s);
  m.Free;
 
end.

Scotty
Beiträge: 768
Registriert: Mo 4. Mai 2009, 13:24
OS, Lazarus, FPC: Arch Linux, Lazarus 1.3 r44426M FPC 2.6.4
CPU-Target: x86_64-linux-qt/gtk2
Kontaktdaten:

Re: Kleines Crash-Quiz

Beitrag von Scotty »

"m :=", das sind aber vier Zeichen 8)

Straightdog
Beiträge: 10
Registriert: Mo 1. Aug 2011, 18:52

Re: Kleines Crash-Quiz

Beitrag von Straightdog »

Ha - das ist das Schöne am Programmieren: es gibt immer mehr als einen Weg zum Ziel.

Deine Lösung ist nämlich völlig korrekt - du musst das Leerzeichen ja nicht löschen und ich habe nicht gesagt, dass die 3 Zeichen hintereinander stehen müssen. Trotzdem, das ist nicht die Lösung die ich suche.

Außerden... das wäre ein einfacher und recht offensichtlicher Programmierfehler, bei dem einen der Compiler sogar eine Warnung liefert. Ich suche eine etwas subtilere Lösung, ohne Compilerwarnungen. Und ich hoffe, dass die Lösung auch für manchen erfahrenen Pascal-Programmierer überraschend ist.

Benutzeravatar
theo
Beiträge: 10907
Registriert: Mo 11. Sep 2006, 19:01

Re: Kleines Crash-Quiz

Beitrag von theo »

Ein Zeichen löschen reicht eigentlich:

Code: Alles auswählen

procedure TMyClass.SetFField(const s: string);
begin
  Field := s;
end;

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Kleines Crash-Quiz

Beitrag von Socke »

theo hat geschrieben:Ein Zeichen löschen reicht eigentlich:

Code: Alles auswählen

procedure TMyClass.SetFField(const s: string);
begin
  Field := s;
end;
Das gleiche kann man dann auch in der GetFField-Methode machen …
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Straightdog
Beiträge: 10
Registriert: Mo 1. Aug 2011, 18:52

Re: Kleines Crash-Quiz

Beitrag von Straightdog »

Und noch 'ne Lösung.

Schöne Endlosrekursionen (na ja, endlos bis der Stack voll ist). Aber noch nicht subtil genug. :wink:

Wobei... Frage: hätte der Compiler hier die Chance einen zu warnen? Mit anderen Worten: wäre es sinnvol, eine Rekursionswarnung zu haben, wenn

(a) eine Funktion/Prozedur sich selbst aufruft (auch indirekt, zumindest für Fälle in denen dies in zumutbarer Zeit feststellbar ist, wie z.B. bei Gettern/Settern von Eigenschaften)
und
(b) der Aufruf bedingungslos erfolgt (sprich: es gibt weder Exit, if noch case vor dem Aufruf).

Warnung, kein Fehler, denn die Rekursion könnte ja auch über die Ausnahmebehandlung abgebrochen werden.

Maik81ftl
Beiträge: 619
Registriert: Mi 9. Mär 2011, 16:34
OS, Lazarus, FPC: Ubuntu10.04 LTS (L 0.9.31.0 FPC 2.4.4)
CPU-Target: 64Bit
Wohnort: seit 01.06.2011 in Wahlstedt

Re: Kleines Crash-Quiz

Beitrag von Maik81ftl »

Code: Alles auswählen

function TMyClass.GetFField: string;
begin
  Result := FField;
end;
 
procedure TMyClass.SetFField(const s: string);
begin
  FField := s;
end;
 
procedure TMyClass.Clear;
begin
  FField := '';
end;
Würde bei den o.g. Functionen FField in Field ändern. ergo

Code: Alles auswählen

function TMyClass.GetFField: string;
begin
  Result := Field;
end;
 
procedure TMyClass.SetFField(const s: string);
begin
  Field := s;
end;
 
procedure TMyClass.Clear;
begin
  Field := '';
end;
Ubuntu 10.04 LTS ist meine Heimat. Lazarus ist meine Sprache :D und der Kreis Segeberg meine LIEBE :D

Straightdog
Beiträge: 10
Registriert: Mo 1. Aug 2011, 18:52

Re: Kleines Crash-Quiz

Beitrag von Straightdog »

Sucht mal eine Lösung, bei der das Programm abstürzt, wenn man 3 Zeichen entfernt, aber ohne Absturz bleibt, wenn man zusätzlich "string" durch "shortstring" ersetzt (oder schlicht das {$H+} entfernt).

Maik81ftl
Beiträge: 619
Registriert: Mi 9. Mär 2011, 16:34
OS, Lazarus, FPC: Ubuntu10.04 LTS (L 0.9.31.0 FPC 2.4.4)
CPU-Target: 64Bit
Wohnort: seit 01.06.2011 in Wahlstedt

Re: Kleines Crash-Quiz

Beitrag von Maik81ftl »

Straightdog hat geschrieben:Sucht mal eine Lösung, bei der das Programm abstürzt, wenn man 3 Zeichen entfernt, aber ohne Absturz bleibt, wenn man zusätzlich "string" durch "shortstring" ersetzt (oder schlicht das {$H+} entfernt).
:?: :?: :?:
Ubuntu 10.04 LTS ist meine Heimat. Lazarus ist meine Sprache :D und der Kreis Segeberg meine LIEBE :D

Straightdog
Beiträge: 10
Registriert: Mo 1. Aug 2011, 18:52

Re: Kleines Crash-Quiz

Beitrag von Straightdog »

Maik81ftl, ich habe dieses kleine Quiz hier gepostet, weil ich gerne über eine - meiner Meinung nach merkwürdige bzw. schlechte - Eigenschaft von FreePascal (aber auch Delphi) diskutieren möchte. Das Quiz sollte als Einstieg dienen. Darum habe ich eine ganz bestimmte Lösung im Kopf - und diese Lösung hängt davon ab, dass TMyClass mit strings (genauer: ansistrings) arbeitet. Ersetzt man die ansistrings in diesem Programm also durch shortstrings, dann funktioniert die von mir gesuchte Lösung nicht mehr.

Ich habe die oben erwähnte Eigenschaft für einen Compiler-Fehler gehalten, wurde aber darüber belehrt, dass sie kein Bug, sondern ein Feature ist. Und dass sie allen besseren Pascal-Programmierern wohlbekannt sei, weshalb es auch keinerlei Probleme damit geben könne. Das wollte ich testen, deshalb dieses Quiz. Denn in diesem Forum sollten ein paar bessere Pascal-Programmierer mitlesen, und für die sollte es kein Problem sein. das Programm auf die von mir gewünschte Art zum Absturz zu bringen.

Nochmal:
3 Zeichen entfernen (stehen sogar unmittelbar hintereinander) -> Absturz.
Danach alle Vorkommen von string durch shortstring ersetzen -> kein Absturz, aber ein anderes Ergebnis (Bildschirmausgabe) als das Original.
-oder-
2 * 5 weitere Zeichen löschen (also zwei 5 Zeichen lange Wörter) -> auch kein Absturz (und das Programm liefert dasselbe Ergebnis wie das Original).

Maik81ftl
Beiträge: 619
Registriert: Mi 9. Mär 2011, 16:34
OS, Lazarus, FPC: Ubuntu10.04 LTS (L 0.9.31.0 FPC 2.4.4)
CPU-Target: 64Bit
Wohnort: seit 01.06.2011 in Wahlstedt

Re: Kleines Crash-Quiz

Beitrag von Maik81ftl »

Ergo den Compilerschalter

Code: Alles auswählen

{$H+}
löschen bzw. Ausklammern und schon kann das programm Anstürzen?!
Ubuntu 10.04 LTS ist meine Heimat. Lazarus ist meine Sprache :D und der Kreis Segeberg meine LIEBE :D

Scotty
Beiträge: 768
Registriert: Mo 4. Mai 2009, 13:24
OS, Lazarus, FPC: Arch Linux, Lazarus 1.3 r44426M FPC 2.6.4
CPU-Target: x86_64-linux-qt/gtk2
Kontaktdaten:

Re: Kleines Crash-Quiz

Beitrag von Scotty »

"Test + Test" ist doch noch immer ein Shortstring.
Prinzipiell hast du aber recht. Ich habe die Tage eine Klasse in eine Unit ausgelagert und dabei vergessen, das H+ anzugeben. Bei der Datenübertragung wurden deswegen die Strings ohne Warnung bei Zeichen #255 abgeschnitten. Ich habe eine Weile nach der Ursache suchen müssen ;-).

Heinrich Wolf
Beiträge: 323
Registriert: Di 12. Apr 2011, 13:21
OS, Lazarus, FPC: WinXP + VMWare Player mit Fedora14, L 1.1, FPC 2.7.1
CPU-Target: 1core 1,8GHz 32Bit
Wohnort: Fürth
Kontaktdaten:

Re: Kleines Crash-Quiz

Beitrag von Heinrich Wolf »

Wieso stürzt das Programm ab, wenn man zwei ShortStrings verkettet?

Straightdog
Beiträge: 10
Registriert: Mo 1. Aug 2011, 18:52

Re: Kleines Crash-Quiz

Beitrag von Straightdog »

Verdammt, ich versuche die Sache klarer darzustellen und verwirre nur alle.

Deshalb jetzt mal die von mir gesuchte Lösung:

Ersetzt

Code: Alles auswählen

property Field: string read GetFField write SetFField;
durch

Code: Alles auswählen

property Field: string read FField write SetFField;
(statt eines "Getters" also direkter Zugriff auf das Feld) und schon stürzt das Programm ab. Wenn ihr danach {$H+} löscht (also shortstrings statt ansistrings verwendet), dann läuft es wieder ohne Absturz.

Womit wir zur eigentlichen Quizfrage kommen: Warum stürzt es mit FField ab? Und warum hat es vorher mit GetFField funktioniert?

Scotty
Beiträge: 768
Registriert: Mo 4. Mai 2009, 13:24
OS, Lazarus, FPC: Arch Linux, Lazarus 1.3 r44426M FPC 2.6.4
CPU-Target: x86_64-linux-qt/gtk2
Kontaktdaten:

Re: Kleines Crash-Quiz

Beitrag von Scotty »

Verblüffend! Ohne H+ wird aber das zweite Set nicht korrekt ausgeführt (Leerstring kommt raus). Und woher kommt nun der Error?

Antworten