![]() |
Pointer-Problem
Hi,
ich nutze einige Objekte zur Datenverwaltung und lasse die in ggf. Listen sortieren. Gestern bekam ich ein Problem, das ich mir nicht erklären kann. Eine Sortierfunktion knallt mir gelegentlich um die Ohren. Nach einiger Suche fand ich heraus, dass die Pointer i.d.R. so um die $0800.0000 liegen. Gelegentlich ist dann einer über $1000.0000 dabei, was zu einer Zugriffsverletzung führt. Also habe ich vor der Sortierung die Liste untersucht. Da ist aber noch alles i.O.!? Natürlich kann ich nochmal alles neu aufbauen und z.B. eine generische Liste nutzen, aber irgendwie muss sich das Problem doch finden lassen. Hat da jemand eine Idee?
Delphi-Quellcode:
function ListSortCompetitors(Item1, Item2: Pointer): Integer;
var C1, C2: TodCompetitor; begin if Integer(Item1) >= $10000000 then begin Exit(0); // Zugriffsfehler vermeiden end; if Integer(Item2) >= $10000000 then begin Exit(0); // Zugriffsfehler vermeiden end; if TComponent(Item1).ClassName <> 'TodCompetitor' then begin beep; end; if TComponent(Item2).ClassName <> 'TodCompetitor' then begin beep; end; C1 := TodCompetitor(Item1); C2 := TodCompetitor(Item2); if C1.Tag <> C1.GameParty.Tag then begin beep; end; if C2.Tag <> C2.GameParty.Tag then begin beep; end; Result := CompareValue(C2.GameParty.PlayerList.Count, C1.GameParty.PlayerList.Count); if Result = 0 then Result := Random(3) - 1; end; // ... // CL ist ein Container, der intern eine einfache Liste verwaltet for I := 0 to CL.Count - 1 do // Liste vor Sort prüfen begin // CodeSite.Send(inttostr(CL.Competitor(I).GameParty.PlayerList.Count)); if Integer(Pointer(CL.Competitor(I))) > $10000000 then begin beep; // kommt nicht vor end; if not odExist(CL.Competitor(I)) then begin beep; // kommt nicht vor end; if CL.Competitor(I).Tag <> Succ(I) then begin beep; // kommt nicht vor end; if not odExist(CL.Competitor(I).GameParty) then begin beep; // kommt nicht vor end; if CL.Competitor(I).GameParty.Tag <> Succ(I) then begin beep; // kommt nicht vor end; end; if CL.Count > 1 then CL.Items.Sort(ListSortCompetitors); // Liste Sortieren - gelegentlich Zugriffsfehler ... |
AW: Pointer-Problem
Moin,
du könntest da ein Problem im Sortieralgorythmus haben, weil sich die Datenmenge ändert:
Delphi-Quellcode:
Bei Gleichheit sortiert er mal so und mal so. Schaffe anders eine sichere Sortierfolge. Du könntest den Pointer auf Integer casten und damit bei Gleichheit vergleiche.
Result := CompareValue(C2.GameParty.PlayerList.Count, C1.GameParty.PlayerList.Count);
if Result = 0 then Result := Random(3) - 1; Stefan |
AW: Pointer-Problem
Das dachte ich auch schon, aber eine Sortierfunktion nur mit
Delphi-Quellcode:
macht keine Probleme.
Result := Random(3) - 1;
Ich dachte dann, dass u.U. vielleicht durch die Zufallswerte ein paar "unnötige Vergleiche" durchgeführt werden, was aber letztlich kein wirkliches Problem wäre. Wenn ich die Pointer vergleiche, hätte ich ja eine feste Reihenfolge, was ich gerade vermeiden will. Ich kann ja mal testweise in Tag einen Zufallswert schreiben und darauf vergleichen. Aber irgendwie komisch, das Ganze. Wo dieser komische Pointer her kommt, ist mir halt unklar. Ach so ... Ich weiß jetzt gar nicht, welches Sortierverfahren List.Sort nutzt (kann ich später erst nachschauen). Evtl. sind die Reihenfolgen bei 0 ja ohnehin undefiniert - dann könnte ich mir das ganze randomieren ;-) auch sparen. |
AW: Pointer-Problem
Versuch es doch mal so:
Delphi-Quellcode:
Gruß
C1 := TodCompetitor(Item1^);
C2 := TodCompetitor(Item2^); K-H |
AW: Pointer-Problem
Zitat:
In einem Win32-Programm kann ein Pointer locker bis $7FFFFFFF gehn und bei aktivierter 3 GB-Speicherverwaltung auch noch viel weiter hoch. Bei dir müssen Pointer innerhalb der ersten 256 MB des virtuellen Arbeitsspeichers liegen, wo sie zu mindetens 88% ganz bestimmt nicht liegen werden. (bis zu durchschnittlich 94% bei 3-4 GB) |
AW: Pointer-Problem
Vorab wird CL.Competitor geprüft, sortiert wird aber CL.Items.
Stellt sich die Frage, was ist da überhaupt drin und wie kommt es da rein. |
AW: Pointer-Problem
Ok, gelöst: In der Sortfunktion mit Random zu arbeiten, ist offenbar keine gute Idee. Scheinbar haut das u.U. die Items etwas durcheinander.
Ich habe einfach mal dem Tag der Einträge einen Zufallswert zugewiesen und so funktioniert das sofort perfekt.
Delphi-Quellcode:
Auch Result immer 0 zuzuweisen führt zu einer gewissen zufälligen Sortierung. Allerdings sind davon nicht alle Einträge betroffen.
if CL.Count > 1 then
begin for I := 0 to CL.Count - 1 do CL.Competitor(I).Tag := Random($FFFF); CL.Items.Sort(ListSortCompetitors); end; @Blup CL.Competitor(I) castet letztlich CL.Items[I]. Ich kann leider nicht mit Generics arbeiten, da die RTTI mit generischen Klassen nicht ausreichend zurecht kommt und ích die Objekte serialisiere. |
AW: Pointer-Problem
So, hier erstmal der Comparer mit einer ordentlichen Typkonvertierung
Delphi-Quellcode:
function ListSortCompetitors(Item1, Item2: Pointer): Integer;
var C1, C2: TodCompetitor; begin C1 := TObject(Item1) as TodCompetitor; C2 := TObject(Item2) as TodCompetitor; Result := CompareValue(C2.GameParty.PlayerList.Count, C1.GameParty.PlayerList.Count); if Result = 0 then Result := Random(3) - 1; end;
Delphi-Quellcode:
Ansonsten ist die Unterschreidung nach Speicheradresse kommplett falsch gedacht, denn die Verteilung im Speicher ist willkürlich und wie schon erwähnt, sind Werte über $10000000 vollkommen plausibel und definitiv kein Erkennungsmerkmal für einen "defekten" Pointer. (vorallem wenn dein Arbeitsspeicher mal etwas voller wird).
function ListSortCompetitors(Item1, Item2: Pointer): Integer;
begin Result := CompareValue((TObject(Item2) as TodCompetitor).GameParty.PlayerList.Count, (TObject(Item1) as TodCompetitor).GameParty.PlayerList.Count); if Result = 0 then Result := Random(3) - 1; end; Wenn bei dieser Funktion Zeiger defekt sind, dann sind vermutlich die schon die Zeiger defekt, welche sich in deiner Liste befinden. Liegt es nicht an der Liste liegt, dann könnte es höchstens noch daran liegen, daß deine Zufallswerte den Sortieralgo durchdrehen lassen und dieser z.B. über die Arraygrenzen seiner Liste hinausläuft. Aber auch das dürfte nicht passieren und ich würde sowas dann eher als einen Bug im Sortieralgorithmus abstempeln. (auch wenn es nicht so einfach ist, wenn man versucht sich ständig verändernde Werte zu sortieren, welche sich wärend des Sortierens verändern, ohne daß man sie vorher zwischenspeichert) |
AW: Pointer-Problem
Ich habe jetzt öfters die Random() Funktion hier gesehen;
also wenn das Ziel sein sollte eine Liste durch Sortieren (Quicksort) in eine zufällige Reihenfolge zu bringen, dann ist ein suboptimaler Weg. Dafür sollte man den ![]() |
AW: Pointer-Problem
Den TypeCast hatte ich schon mit TComponent(Item1) versucht, was auch schon zu einem Fehler führte.
Offenbar toleriert die SortRoutine wirklich nicht die Zufallswert-Zuweisung und "dreht durch" bzw. schmeißt irgendwelche temporäre Adressen durcheinander (oder was auch immer). Auf jeden Fall ist vor Sort noch alles i.O. und während der Sortierung kracht es dann. Ob man das als Bug bezeichnen muss, weiß ich nicht recht. Ich wollte es mir möglichst einfach machen und gleichrangige Einträge nochmal verwürfeln. Aber dann geht das halt auf dem Weg nicht (oder jedenfalls nicht zuverlässig). |
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:11 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