Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Fehler beim Dynamischen Array? (https://www.delphipraxis.net/5396-fehler-beim-dynamischen-array.html)

X-Dragon 4. Jun 2003 16:08


Fehler beim Dynamischen Array?
 
In meinem Programm erhalte ich immer einen Speicherfehler, aber was ist da falsch?

Delphi-Quellcode:
var
  anz : Integer;
  ObjList : array of TMeinObjekt;
/...
  for i := 0 to MeineObjektListe-1 do
  begin
    obj := TMeinObjekt(MeineObjektListe.Objects[i]);
    if obj.xyz := 'xyz' then
    begin
      Inc(anz);
      SetLength(ObjList, anz);
      ObjList[anz-1].Assign(objsuch); // hier tritt der Fehler auf ...
    end;
  end;
... er bricht er also schon vor Abarbeitung der Assign-Prozedur ab (=kopieren der Inhalte von einem Objekt ins andere).

Jens Schumann 4. Jun 2003 16:58

Hallo,
dein Source läßt vermuten, dass Du anz vor der Schleife nicht auf
einen definierten Anfangswert setzt (Stichwort: Initialisieren).
Schreib mal vor die Schleife anz:=0;
Lokale Variablen werden auf dem Stack angelegt. Wenn Du anz nicht initialisierst kann jeder beliebige Wert in anz stehen. Nämlich genau der Wert, den irgendein anderer Programmteil an der Speicherstelle hinterlassen hat.

Christian Seehase 4. Jun 2003 18:11

Moin X-Dragon,

ausserdem solltest Du das Array mit einer sinnvollen Grösse vor der Schleife dimensionieren, und erst wenn diese nicht ausreicht um eine sinnvolle Anzahl (i.d.R. wohl nicht 1).
Dadurch entlastest Du die Speicherverwaltung erheblich, die sonst bei jeder Vergrösserung des Arrays dieses meist erst mal umkopieren muss, was wiederum erheblich auf die Performance drücken kann.

Da Du die maximal mögliche Grösse kennst (MeineObjektListe) kannst Du das Array auch gleich auf diesen Wert dimensionieren.

X-Dragon 4. Jun 2003 20:59

Zitat:

Zitat von Jens Schumann
Hallo,
dein Source läßt vermuten, dass Du anz vor der Schleife nicht auf
einen definierten Anfangswert setzt (Stichwort: Initialisieren).
Schreib mal vor die Schleife anz:=0;
Lokale Variablen werden auf dem Stack angelegt. Wenn Du anz nicht initialisierst kann jeder beliebige Wert in anz stehen. Nämlich genau der Wert, den irgendein anderer Programmteil an der Speicherstelle hinterlassen hat.

"anz" wird vor der Schleife auf 0 gesetzt, hab ich nur beim kopieren vergessen :oops:.

Zitat:

Zitat von Christian Seehase
Moin X-Dragon,

ausserdem solltest Du das Array mit einer sinnvollen Grösse vor der Schleife dimensionieren, und erst wenn diese nicht ausreicht um eine sinnvolle Anzahl (i.d.R. wohl nicht 1).
Dadurch entlastest Du die Speicherverwaltung erheblich, die sonst bei jeder Vergrösserung des Arrays dieses meist erst mal umkopieren muss, was wiederum erheblich auf die Performance drücken kann.

Da Du die maximal mögliche Grösse kennst (MeineObjektListe) kannst Du das Array auch gleich auf diesen Wert dimensionieren.

Achso danke, dann werd ich wohl doch besser vorher die richtig Anzahl feststellen. MeineObjektListe kann durchaus mehrere hundert Einträge haben, aber normal werden dort nicht mehr als 10 davon benötigt, deshalb die if-Abfrage (habs stark vereinfacht damit es übersichtlicher ist).

Christian Seehase 4. Jun 2003 22:58

Moin X-Dragon,

also ich für meinen Teil versuche in so einem Falle die erforderliche Grösse gezielt zu "raten", und mir zusätzlich einen Wert festzulegen, um den ich das Array vergrössere, falls es doch nicht reicht.
Dann muss ich zwar immer testen, ob der nächste einzutragende Wert noch reinpasst, aber dass ist ja nur ein kurzer numerischer Vergleich, der nicht viel Zeit kostet.

Motzi 5. Jun 2003 07:46

Für Objekte empfehl ich überhaupt auf ein dyn. Array zu verzichten und stattdessen eine TList oder TObjectList zu verwenden...

X-Dragon 5. Jun 2003 08:15

Stimmt die Idee mit dem schätzen ist auch nicht schlecht, da ich ja ungefähr weiß was normal als Ergebnis rauskommt.

Da es mit dem kopieren des Objektes aber leider nicht funktioniniert(das werd ich mir demnächst nochmal genauer anschauen), hab ich jetzt alles umgestellt und speichere die Einträge in einer Stringliste, deshalb fällt das dynamische Array wie auch der Zähler erstmal weg.

@Motzi
Danke für den Tip, hab ich gerade gemacht :).

Delphi-Quellcode:
var
  i, j : Integer;
  objsuch : TTermine;
  objids : TStrings;
begin
  objids := TStringList.Create;
  InitTermine(True); // aktualisieren der TermineListe

  for i := 0 to TermineListe.Count -1 do
  begin
    objsuch := TTermine(TermineListe.Objects[i]);
    if (objsuch.SettWert = auft.SettWert) and
       (objsuch.Notitz = auft.Notitz) then
    begin
      objsuch.LW := True; // Zugriff auf Datensatz für andere User sperren
      objsuch.Speichern;
      ObjIDs.AddObject(objsuch.ID, objsuch); // speichern der ID und des Objektes
    end;
  end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:28 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-2025 by Thomas Breitkreuz