Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Abstrakter Fehler oO (https://www.delphipraxis.net/77326-abstrakter-fehler-oo.html)

Green 17. Sep 2006 23:18


Abstrakter Fehler oO
 
Delphi-Quellcode:
function GetId(f: string; i: integer): string;
  var
    temp: string;
    j: integer;
    sl: TStrings;
begin
  temp := '';
  sl := TStrings.Create;
  sl.LoadFromFile(f);
  for j := 0 to 4 do begin
    temp := temp + sl[0][(i * 6) + j];
  end;
  result := temp;
end;
Delphi-Quellcode:
ShowMessage(GetId('ids.txt', 0));
Warum kommt da n Abstrakter Fehler und was zur Hölle is des???

GuenterS 17. Sep 2006 23:20

Re: Abstrakter Fehler oO
 
Das kommt immer dann, wenn Du von akstrakte, also nicht implementierte Methoden aufrufst. In Deinem Beispiel passiert dies, weil Du eine Instance von TStrings erstellt, welche viele abstrakte Methoden besitzt. Besser wäre hier TStringList gewesen, was diesen Fehler beheben dürfte.


Die erzeugte StringList solltest Du aber auch wieder freigeben, am ende der Procedure, sonst erzeugst Du ein schones Memory leak.

mkinzler 17. Sep 2006 23:21

Re: Abstrakter Fehler oO
 
Das kommt weil TStrings abstrakt ist, ersetze
Delphi-Quellcode:
sl := TStrings.Create;
mit
Delphi-Quellcode:
sl := TStringList.Create;

Martin K 17. Sep 2006 23:27

Re: Abstrakter Fehler oO
 
Mit der Freigabe und einem Try...finally-Block könnte es dann so aussehen:
Delphi-Quellcode:
function GetId(f: string; i: integer): string;
  var
    j: integer;
    sl: TStrings;
begin
  result := '';
  sl := TStringList.Create;
  try
    sl.LoadFromFile(f);
    for j := 0 to 4 do
      result := result + sl[0][(i * 6) + j];
  finally
    FreeAndNil(sl);
  end;
end;
Übrigens: Die zusätzliche String-Variable kann man sich auch sparen, wenn man gleich result verwendet :wink:

Matze 17. Sep 2006 23:31

Re: Abstrakter Fehler oO
 
Zitat:

Zitat von Martin K
Übrigens: Die zusätzliche String-Variable kann man sich auch sparen, wenn man gleich result verwendet :wink:

Ich habe irgendwo einmal gelesen, dass man der Result-Variablen möglichst nur ein einziges Mal etwas zuweisen sollte und zwar am Ende der Funktion. In einer Schleife sollte man das nicht machen. Aber wieso, habe ich vergessen. :oops:

Ich würde also die ursprüngliche Möglichkeit bevorzugen.

GuenterS 17. Sep 2006 23:32

Re: Abstrakter Fehler oO
 
Zitat:

Zitat von Martin K
Mit der Freigabe und einem Try...finally-Block könnte es dann so aussehen:
Delphi-Quellcode:
function GetId(f: string; i: integer): string;
  var
    j: integer;
    sl: TStrings;
begin
  result := '';
  sl := TStringList.Create;
  try
    sl.LoadFromFile(f);
    for j := 0 to 4 do
      result := result + sl[0][(i * 6) + j];
  finally
    FreeAndNil(sl);
  end;
end;
Übrigens: Die zusätzliche String-Variable kann man sich auch sparen, wenn man gleich result verwendet :wink:

Man kann sich ausserdem noch die Variable "j" sparen.
Delphi-Quellcode:
function GetId(f: string; i: integer): string;
var
    sl: TStringList;
begin
  sl := TStringList.Create;
  try
    sl.LoadFromFile(f);
    result := sl[0][(i*6)] + sl[0][(i*6)+1] + sl[0][(i*6)+2] + sl[0][(i*6)+3] + sl[0][(i*6)+4];
  finally
    FreeAndNil(sl);
  end;
end;

Zitat:

Zitat von Matze
Zitat:

Zitat von Martin K
Übrigens: Die zusätzliche String-Variable kann man sich auch sparen, wenn man gleich result verwendet :wink:

Ich habe irgendwo einmal gelesen, dass man der Result-Variablen möglichst nur ein einziges Mal etwas zuweisen sollte und zwar am Ende der Funktion. In einer Schleife sollte man das nicht machen. Aber wieso, habe ich vergessen. :oops:

Ich würde also die ursprüngliche Möglichkeit bevorzugen.

Hm, ich setze Result auch gerne mal am Anfang, für den Fall dass was schiefgeht auf einen eindeutigen Wert. Wenn Du wieder weißt wo das steht, würds mich intressieren, das auch zu lesen. Bzw. welchen Grund dieses hat.

mkinzler 17. Sep 2006 23:37

Re: Abstrakter Fehler oO
 
Die result Varibale sollte man nur am Schluß setzen.
Ich galube in der heutigen Zeit sollte man die Lesbarkeit vor das Sparen von ein paar Bytes setzen.

Martin K 17. Sep 2006 23:41

Re: Abstrakter Fehler oO
 
Zitat:

Zitat von Matze
Ich habe irgendwo einmal gelesen, dass man der Result-Variablen möglichst nur ein einziges Mal etwas zuweisen sollte und zwar am Ende der Funktion. In einer Schleife sollte man das nicht machen. Aber wieso, habe ich vergessen. :oops:

Echt?
Das wäre mir neu.

Aber Result am Anfang auf einen leeren String zu setzen und dann nachher auf die gewünschten Werte, macht Sinn - sonst könnte das Ergebnis bei einem Fehlschlag undefiniert sein.

Zitat:

Zitat von GuenterS
Man kann sich ausserdem noch die Variable "j" sparen.

Wenn wir jetzt noch die Parameter als Konstanten festlegen ist es Perfekt, außerdem kann man es wohl noch weiter vereinfachen:
Delphi-Quellcode:
function GetId(const f: string; const i: integer): string;
var sl: TStrings;
begin
  result := '';
  sl := TStringList.Create;
  try
    sl.LoadFromFile(f);
    result := Copy(sl[0], i*6, 5);
  finally
    FreeAndNil(sl);
  end;
end;
Was haltet ihr davon?

Luckie 17. Sep 2006 23:42

Re: Abstrakter Fehler oO
 
Delphi legt das Funktionsergebnis in dem Register EAX ab. Wenn ich nun der interne Result Variable etwas zuweise am Anfang wrd das un EAX abgelegt. Optimiert der Compiler nun den Code, hat er ein Register weniger, dass er benutzen kann bzw. erst wieder frei machen muss und zum Schluss wieder belegt. Weise ich Result am Schluss zu, hat der Compiler das EAX Register noch für Optimierungen frei.

Zitat:

Zitat von Martin K
Aber Result am Anfang auf einen leeren String zu setzen und dann nachher auf die gewünschten Werte, macht Sinn - sonst könnte das Ergebnis bei einem Fehlschlag undefiniert sein.

Man kan auch anders sicherstellen, dass der Rückgabewert nicht undefiniert ist:
Delphi-Quellcode:
var
  s: String;
begin
  s := '';
  // mach was
  Result := s;
end;

GuenterS 17. Sep 2006 23:43

Re: Abstrakter Fehler oO
 
@mkinzler:
Hast auch wieder recht, irgendwie würds mich aber schon intressieren was so in der Datei stehen mag, dass man sie komplett einlesen muss, um schlussendlich nur die erste Zeile zu verwenden. Desweiteren fehlt da noch jede Prüfung ob diese erste Zeile überhaupt lang genug ist.

@luckie:
Danke für die Information, wieder was gelernt.

mkinzler 17. Sep 2006 23:44

Re: Abstrakter Fehler oO
 
Das Initialisieren von Result ist nicht nötig. Ich würde das
Delphi-Quellcode:
result := '';
besser ins finally verschieben.

Luckie 17. Sep 2006 23:45

Re: Abstrakter Fehler oO
 
Zitat:

Zitat von mkinzler
Das Initialisieren von Result ist nicht nötig. Ich würde das
Delphi-Quellcode:
result := '';
besser ins finally verschieben.

Dann kann ich mir den restlichen Code aber sparen, da der finally-Block immer ausgeführt wird. Result wäre somit immer der Leerstring. Und da sist wohl nicht Sinn und Zweck der Funktion. ;)

mkinzler 17. Sep 2006 23:46

Re: Abstrakter Fehler oO
 
Zitat:

Zitat von Luckie
Zitat:

Zitat von mkinzler
Das Initialisieren von Result ist nicht nötig. Ich würde das
Delphi-Quellcode:
result := '';
besser ins finally verschieben.

Dann kann ich mir den restlichen Code aber sparen, da der finally-Block immer ausgeführt wird. Result wäre somit immer der Leerstring. Und da sist wohl nicht Sinn und Zweck der Funktion. ;)

Stimmt :oops: Es ist spät ...

Martin K 17. Sep 2006 23:47

Re: Abstrakter Fehler oO
 
Ihr meint wohl sowas:
Delphi-Quellcode:
function GetId(const f: string; const i: integer): string;
var temp: String; sl: TStrings;
begin
  temp := '';
  try
    sl := TStringList.Create;
    try
      sl.LoadFromFile(f);
      temp := Copy(sl[0], i*6, 5);
    finally
      FreeAndNil(sl);
    end;
  finally
    result := temp;
  end;
end;

GuenterS 17. Sep 2006 23:49

Re: Abstrakter Fehler oO
 
[edit]Ja, müßte es treffen[/edit]

[edit2]das ist mir auch eingefallen, aber konnte meinen Beitrag nicht komplett entfernen :oops: [/edit2]

Martin K 17. Sep 2006 23:50

Re: Abstrakter Fehler oO
 
[edit]Herrje, diese ganzen Edits...[/edit]

SirThornberry 17. Sep 2006 23:51

Re: Abstrakter Fehler oO
 
das man "result" erst am ende bzw. vor verlassen der Funktion zuweist kommt wohl von anderen Programmiersprachen wie C, C++, PHP etc. wo durch das zuweisen des Rückgabewertes die Funktion gleichzeitig verlassen wird.

mkinzler 17. Sep 2006 23:51

Re: Abstrakter Fehler oO
 
Zitat:

Und wenn das Erzeugen der StringList fehlschlägt?
Dann wird ein Leerstring zurückgeliefert.

Matze 17. Sep 2006 23:51

Re: Abstrakter Fehler oO
 
Zitat:

Zitat von Martin K
Und wenn das Erzeugen der StringList fehlschlägt?

Wann soll das fehlschlagen? Dann müsstest du ja vor jeder Zuweisung ein "try" setzen. ;)

Luckie 17. Sep 2006 23:52

Re: Abstrakter Fehler oO
 
Delphi-Quellcode:
function GetId(const f: string; const i: integer): string;
var temp: String; sl: TStrings;
begin
  temp := '';
  sl := TStringList.Create;
  try
    sl.LoadFromFile(f);
    temp := Copy(sl[0], i*6, 5);
  finally
    result := temp;
    FreeAndNil(sl);
  end;
end;
So sollte es gehen.

GuenterS 17. Sep 2006 23:54

Re: Abstrakter Fehler oO
 
Zitat:

Zitat von Luckie
Delphi-Quellcode:
function GetId(const f: string; const i: integer): string;
var temp: String; sl: TStrings;
begin
  temp := '';
  sl := TStringList.Create;
  try
    sl.LoadFromFile(f);
    temp := Copy(sl[0], i*6, 5);
  finally
    result := temp;
    FreeAndNil(sl);
  end;
end;
So sollte es gehen.

Genau so ist es nicht mehr garantiert *g* Wenn die Stringlist warum auch immer nicht erzeugt ist, befindet man sich noch nicht im gesicherten Bereich, und kommt dann auch nicht in dieses finally. (Zugegeben, habe ich das allerdings noch nicht erlebt, dass eine Stringlist sich nicht erzeugen lies)

Martin K 17. Sep 2006 23:55

Re: Abstrakter Fehler oO
 
Zitat:

Zitat von Matze
Wann soll das fehlschlagen? Dann müsstest du ja vor jeder Zuweisung ein "try" setzen. ;)

Es könnte nicht mehr genügend Speicher verfügbar sein, aber ist ja jetzt auch egal, durch die ganzen Edits ergibt das keinen Sinn mehr...

Aber ja, man könnte den Code von mir aus auch so machen, wie Luckie geschrieben hat.

SirThornberry 17. Sep 2006 23:55

Re: Abstrakter Fehler oO
 
Zitat:

Zitat von Luckie
Delphi-Quellcode:
function GetId(const f: string; const i: integer): string;
var temp: String; sl: TStrings;
begin
  temp := '';
  sl := TStringList.Create;
  try
    sl.LoadFromFile(f);
    temp := Copy(sl[0], i*6, 5);
  finally
    result := temp;
    FreeAndNil(sl);
  end;
end;
So sollte es gehen.

warum steckt man die zuweisung von "result" mit ins finally. bzw. wozu überhaupt "finally" alles was immer ausgefüht werden soll kann man doch auch hinter den try-Block setzen und stattdessen ein try-Except block machen das nur bei einer Exception eine sonderbehandlung statt findet
Delphi-Quellcode:
function GetId(const f: string; const i: integer): string;
var temp: String; sl: TStrings;
begin
  sl := TStringList.Create;
  try
    sl.LoadFromFile(f);
    temp := Copy(sl[0], i*6, 5);
  except
    temp := '';
  end;
  FreeAndNil(sl);
  result := temp;
end;
die variante mit finally kommt ja dieser gleich:
Delphi-Quellcode:
function GetId(const f: string; const i: integer): string;
var temp: String; sl: TStrings;
begin
  temp := '';
  sl := TStringList.Create;
  try
    sl.LoadFromFile(f);
    temp := Copy(sl[0], i*6, 5);
  except
  end;
  result := temp;
  FreeAndNil(sl);
end;

Matze 17. Sep 2006 23:57

Re: Abstrakter Fehler oO
 
Zitat:

Zitat von GuenterS
Genau so ist es nicht mehr garantiert *g* Wenn die Stringlist warum auch immer nicht erzeugt ist, befindet man sich noch nicht im gesicherten Bereich, und kommt dann auch nicht in dieses finally.

Das finally kommt genrell, nur würde es dann krachen. Aber ich habe noch nie gehört, dass eine StringList nicht erstellt werden würde.

GuenterS 18. Sep 2006 00:03

Re: Abstrakter Fehler oO
 
Zitat:

Zitat von Matze
Zitat:

Zitat von GuenterS
Genau so ist es nicht mehr garantiert *g* Wenn die Stringlist warum auch immer nicht erzeugt ist, befindet man sich noch nicht im gesicherten Bereich, und kommt dann auch nicht in dieses finally.

Das finally kommt genrell, nur würde es dann krachen. Aber ich habe noch nie gehört, dass eine StringList nicht erstellt werden würde.

Das stimmt so aber nicht.

Delphi-Quellcode:
procedure Test;
var
  i: integer;
  lList: TList;
begin
  i := 0;
  lList.Add(@i); // <-- Verhängnisvolle Zeile
  try
      ShowMessage('TEST');
  finally
      ShowMessage('FINALLY');
  end;
end;

Habe das gerade eben mal schnell mit TurboDelphi probiert, er kommt nicht zum ShowMessage('FINALLY');

Würde ich die verhängnissvolle Zeile innerhalb des Try Blockes machen schon.

Matze 18. Sep 2006 00:05

Re: Abstrakter Fehler oO
 
Ach so meinst du das. Stimmt, das hatte ich gar nicht bedacht. Aber in jedem Mustercode wird es ohne doppeltes "try" gelöst. Also kann da eigentlich auch nichts passieren.

Martin K 18. Sep 2006 00:10

Re: Abstrakter Fehler oO
 
Natürlich kommt er nur in's finally wenn es vor dem try nicht schon gekracht hat.
D.h. wenn in unserem obigen Beispiel das Erzeugen der StringList fehlschlägt (was eigentlich nicht vorkommen sollte), wird der finally-Teil auch nicht ausgeführt.

Zitat:

Zitat von Matze
Ach so meinst du das. Stimmt, das hatte ich gar nicht bedacht. Aber in jedem Mustercode wird es ohne doppeltes "try" gelöst. Also kann da eigentlich auch nichts passieren.

Also ich arbeite oft mit verschachtelten try..finally-Blöcken, z.B.:
Delphi-Quellcode:
  sl := TStringList.Create;
  try
    //do something
    if sl[0] = 'lad mir ne neue StringList' then
    begin
      sl2 := TStringList.Create;
      try
        // do something
      finally
        FreeAndNil(sl2);
      end;
    end;
  finally
    FreeAndNil(sl);
  end;

Matze 18. Sep 2006 00:13

Re: Abstrakter Fehler oO
 
In dem Fall sollte man das auch, das ist korrekt. ;)


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:58 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz