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.