Einzelnen Beitrag anzeigen

noob2k9

Registriert seit: 1. Aug 2008
13 Beiträge
 
Delphi XE2 Starter
 
#1

Fehler beim Auflösen und Freigeben eines dynamischen Tree's

  Alt 10. Mär 2012, 14:02
Hi DP-User,

ich habe einen Fehler identifiziert der mir nun schon einige Stunden Kopfzerbrechen bereitet.

Während der Laufzeit meines Programmes führe ich eine vollständige Enumeration (mit diversen Abbruchbedingungen) durch und generiere so in einem rekursiven Algorithmus einen Baum dessen Blätter immer auf die übergeordneten Äste/Elemente (Parents) zeigen.
Die Verknüpfung wird nur in eine Richtung "bottom-up" realisiert.

Die Blätter werden in dem Array variations gespeichert, so dass jede gefundene Lösung rekonstruiert werden kann in dem von dem Blatt jedes Parent zurückverfolgt wird bis man bei dem Root-Element ankommt.
Das Root-Element besitzt als Parent einen Pointer auf nil um so dass Ende zu markieren.

Nun stehe ich vor folgendem Problem: Wenn ich versuche den Speicher der durch den entstandenen Baum belegt wird freizugeben erhalte ich eine Zugriffsverletzung beim Schreiben auf den Speicher.
Ich habe die Ursache bereits soweit zurückverfolgt dass ich sagen kann wo der Fehler auftritt, nämlich sobald der Ast bereits "abgesägt" wurde - also ein anderes Child (Blatt) einen ähnlichen Pfad hatte und durch die while ... do - Schleife bis zum Parent/Root aufgelöst wurde.

Ergo: Das Record wurde bereits aufgelöst und der Zeiger zeigt nun irgendwo ins Nirvana.

Ich hoffe ich konnte das Problem ausreichend beschreiben.
Nun zur eigentlichen Frage: Gibt es eine Möglichkeit wie ich dies verhindern kann oder gar eine bessere Möglichkeit den Tree aufzulösen?

Delphi-Quellcode:
type
  T_Container_2D = record
    parent: Pointer;
    x1: Integer;
    y1: Integer;
    x2: Integer;
    y2: Integer;
  end;

type
  T_Variations_2D = Array of Pointer;

procedure Clear();
var
  i, l: Integer;
  now, next: P_Container_2D;
begin
  // Init
  i := 0;
  l := Length(variations) - 1;

  for i := l downto 0 do begin
    now := variations[i];
    while now <> nil do begin
      if now^.parent <> nil then begin
        next := now^.parent;
        FreeMemory(now);
        now := nil;
        now := next;
      end
      else begin
        now := nil;
      end;
    end;
  end;

  SetLength(variations, 0);
end;

Geändert von noob2k9 (10. Mär 2012 um 16:20 Uhr)
  Mit Zitat antworten Zitat