AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

Pointer-Problem

Ein Thema von stahli · begonnen am 26. Jan 2012 · letzter Beitrag vom 26. Jan 2012
Antwort Antwort
Seite 1 von 2  1 2   
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.289 Beiträge
 
Delphi 10.4 Sydney
 
#1

Pointer-Problem

  Alt 26. Jan 2012, 12:21
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 <> 'TodCompetitorthen
  begin
    beep;
  end;
  if TComponent(Item2).ClassName <> 'TodCompetitorthen
  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
...
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)

Geändert von stahli (26. Jan 2012 um 12:23 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von MacGuyver
MacGuyver

Registriert seit: 9. Sep 2003
Ort: Wildeshausen
285 Beiträge
 
Turbo Delphi für Win32
 
#2

AW: Pointer-Problem

  Alt 26. Jan 2012, 12:32
Moin,

du könntest da ein Problem im Sortieralgorythmus haben, weil sich die Datenmenge ändert:

Delphi-Quellcode:
Result := CompareValue(C2.GameParty.PlayerList.Count, C1.GameParty.PlayerList.Count);
   if Result = 0 then
     Result := Random(3) - 1;
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.

Stefan
Englisch eine Weltsprache? Zu kompliziert und der nahe Osten würde Englisch als Pflichtweltsprache nicht akzeptieren.
IDO wäre genau das Richtige: http://forum.idolinguo.de/index.php oder www.idolinguo.de
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.289 Beiträge
 
Delphi 10.4 Sydney
 
#3

AW: Pointer-Problem

  Alt 26. Jan 2012, 12:52
Das dachte ich auch schon, aber eine Sortierfunktion nur mit Result := Random(3) - 1; macht keine Probleme.

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.
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#4

AW: Pointer-Problem

  Alt 26. Jan 2012, 13:08
Versuch es doch mal so:
Delphi-Quellcode:
  C1 := TodCompetitor(Item1^);
  C2 := TodCompetitor(Item2^);
Gruß
K-H
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
40.509 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: Pointer-Problem

  Alt 26. Jan 2012, 13:25
Zitat:
Delphi-Quellcode:
  if Integer(Item1) >= $10000000 then
  begin
    Exit(0); // Zugriffsfehler vermeiden
Was für Zugriffsfehler sollen das denn sein?

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)
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list

Geändert von himitsu (26. Jan 2012 um 13:30 Uhr)
  Mit Zitat antworten Zitat
Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.395 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: Pointer-Problem

  Alt 26. Jan 2012, 16:31
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.
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.289 Beiträge
 
Delphi 10.4 Sydney
 
#7

AW: Pointer-Problem

  Alt 26. Jan 2012, 21:09
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:
  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;
Auch Result immer 0 zuzuweisen führt zu einer gewissen zufälligen Sortierung. Allerdings sind davon nicht alle Einträge betroffen.


@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.
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
40.509 Beiträge
 
Delphi 11 Alexandria
 
#8

AW: Pointer-Problem

  Alt 26. Jan 2012, 21:56
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:
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;
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).

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)
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 16. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#9

AW: Pointer-Problem

  Alt 26. Jan 2012, 22:05
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 Fisher-Yates Algorithmus verwenden.
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.289 Beiträge
 
Delphi 10.4 Sydney
 
#10

AW: Pointer-Problem

  Alt 26. Jan 2012, 22:07
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).
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2   

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:39 Uhr.
Powered by vBulletin® Copyright ©2000 - 2022, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf