Einzelnen Beitrag anzeigen

noob2k9

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

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

  Alt 11. Mär 2012, 16:12
Zitat:
Wo kommen denn die Daten her, bzw. wie navigierst Du von der Wurzel durch den Baum?
Erst einmal noch ein paar mehr Infos: Der Algorithmus soll die Anordnung von (kleineren, gleichbleibenden) Rechtecken in einer größeren Fläche vornehmen. Dabei wird durch Rotation und Translation versucht rekursiv die Lösung zu verbessern. Wird in einer Rekursion kein besseres Ergebnis als dass bis dahin erreichte Maximum erzielt bricht der Algorithmus die Berechnung an dieser Verzweigung natürlich ab und verwirft bis dahin gespeicherte Zweige. Das funktioniert soweit auch ganz gut.

Zitat:
Kannst Du nicht beim Aufbauen bereits eine Liste aller Knoten anlegen.
Das speichern aller Knoten in einem extra Array habe ich auch schon versucht - doch dann stieg der Speicherverbrauch beim letzten Versuch exhorbitant an. Ich habe den Speicherverbrauch seit dem aber weiter senken können indem ich während des Rechenlaufs bereits beginne Speicher freizugeben wenn die Leafs verworfen werden. - Also werde ich diesen Ansatz evtl. nochmals testen.

Zitat:
Leider ist die TObjectList nicht sonderlich schnell, sodaß eine Dictionary hier sicherlich besser geeignet wäre.
Listen möchte ich nicht nutzen da diese von der Performance her nicht so der Brüller sind - es werden unnötige Klassen / Objekte erzeugt die Speicherplatz und Rechenzeit kosten. So gesehen ist der Baum ja auch eine auf das Nötigste reduzierte Liste nur eben mit einer unidirektionalen (und manuell festgelegten) Verknüpfung der Knoten.

Aktuell bin ich wieder auf diesen Ansatz zurück gefallen:
Fehler entstehen bei FreeMem(now); obwohl now auf eine gültige Adresse mit gültigem Datensatz verweisst. (Details weiter unten)
Delphi-Quellcode:
procedure Clear();
var
  i, j, l, c: Integer;
  now, last: P_Container_2D;
  hProcess: THandle;
begin
  // Init
  i := 0;
  l := Length(variations);

  QuickSortPointers(variations, 0, Length(variations) - 1);

  i := 0;
  last := nil;
  if l > 0 then begin
    while i < l do begin
      now := variations[i];
      if (now <> last) then begin
        if Assigned(now) then begin
          last := now;
          FreeMem(now);
        end;
        now := nil;
      end;
      Inc(i);
    end;
  end;

  SetLength(variations, 0);
  variations := nil;

  hProcess := OpenProcess(PROCESS_SET_QUOTA, false, GetCurrentProcessId);
  try
    SetProcessWorkingSetSize(hProcess, $FFFFFFFF, $FFFFFFFF);
  finally
    CloseHandle(hProcess);
  end;
end;
Programmablauf:

1. Vorher:
Code:
Name   Value
now   $2DDC700
parent   $2DDC6E8
x1   30
y1   50
x2   80
y2   70
2. Aufruf von FreeMem(now);

3. Fehlermeldung und Exception: Exception class EInvalidPointer with message 'Invalid pointer operation'.

4. Nachher:
Code:
Name      Value
i      48547632
l      4213291
now      nil
   parent   Inaccessible value
   x1   Inaccessible value
   y1   Inaccessible value
   x2   Inaccessible value
   y2   Inaccessible value
last      $4E1B80
   parent   $FC6163E8
   x1   -1064582145
   y1   -1957210541
   x2   -1946514471
   y2   -1949594640
Edit: Anmerkung: SetProcessWorkingSetSize() nutze ich um den Speicher wieder freizugeben. FastMM4 mit FullDebug-Option berichtet mir keine Speicherlecks.

Edit2: Soeben noch entdeckt das nach dem Aufruf von FreeMem() (bzw. mittlerweile durch Dispose() ersetzt) die ganzen lokalen Variablen der Prozedur verdreht sind ... irgendwo muss ich da einen mächtigen Denkfehler drin haben. i und l nehmen utopische Werte an, und der Pointer auf last ändert sich auch wie durch magische Hand.

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