![]() |
Überprüfen, ob ein Pointer auf ein Objekt zeigt
Hallo Experten, folgendes Problem:
Ich möchte eine Listenklasse erstellen, die von TList abgeleitet ist. In allen Methoden, die einen Pointer zur Liste hinzufügen oder einen entfernen, möchte ich, falls es sich bei dem übergebenen Pointer um ein Objekt eines bestimmten Typs handelt, eine Methode davon aufrufen. Zur Überprüfung, ob es sich um diesen Typ handelt, benutze ich den is-Operator. Diese Liste möchte ich applikationsweit als Ersatz von TList verwenden. Das funktioniert auch wunderbar, solange die Liste ausschließlich mit Objekten gefüttert wird. Aber wehe, man versucht das mit Zeigern auf Records, dann gibt es eine AV - hier ein Beispiel:
Delphi-Quellcode:
Ich bin mir darüber im klaren, dass der Cast auf TObject an sich schon problematisch ist - aber mir fällt keine andere Möglichkeit ein, herauszufinden um was es sich bei dem Pointer handelt. Natürlich könnte man die Exception abfangen und dann davon ausgehen, dass AItem kein Objekt ist, aber das fände ich auch unsauber.
type
TMyObject = class (TObject) { Der Typ, auf den ich prüfen möchte } public procedure DoSomething(); {...} end; TMyList = class (TList) public function Add (AItem : Pointer) : Integer; reintroduce; {...} end; implementation function TMyList.Add (AItem : Pointer) : Integer; var obj : TObject; begin obj := AItem; { Cast auf TObject, um "is" anwenden zu können } if obj is TMyObject then { <== hier schepperts, wenn AItem ein "normaler" Zeiger ist } TMyObject (AItem).DoSomething; Result := inherited Add (AItem); end; Kann jemand helfen? |
Re: Überprüfen, ob ein Pointer auf ein Objekt zeigt
Sowas ist nicht 100%ig möglich.
einzige wirkliche Lösung: Pointer und Objekte getrennt verwalten
Delphi-Quellcode:
liefert bei Objekten richtige Lösungen (solange das Objekt nicht durch z.B. einen Bufferoverflow zerstört wurde),
TObject(P) is TXyz
aber in anderen Daten, wie z.B. einem Record, können zufällig Werte vorhanden sein, welche der "Signatur" eines Objektes entsprechen, wodurch der Record dann als Objekt erkannt würde. |
Re: Überprüfen, ob ein Pointer auf ein Objekt zeigt
Zitat:
|
Re: Überprüfen, ob ein Pointer auf ein Ojekt zeigt
Delphi-Quellcode:
Konnts mir nicht verkneifen :stupid:
function PointsToObj(P: Pointer): Boolean;
begin try Result := TObject(P).ClassName <> ''; except Result := false; end; end; |
Re: Überprüfen, ob ein Pointer auf ein Objekt zeigt
Hallo,
der folgende Code basiert auf einer ![]()
Delphi-Quellcode:
Die Anmerkung von himitsu bezüglich der getrennten Verwaltung von Pointern und Objekten sollte trotzdem beachtet werden. Der Code könnte aber beim Debuggen nützlich sein.
function IsValidObject (const aObject: TObject): Boolean;
type PVmt = ^TVmt; TVmt = packed record SelfPtr: TClass; ignored: array [0..-(4 + vmtSelfPtr) - 1] of Byte; end; var VMT: PVmt; begin Result := False; if {Windows.}IsBadReadPtr(aObject, 4) then Exit; VMT := PVmt(aObject.ClassType); Dec (VMT); if IsBadReadPtr(VMT, 4) then Exit; if (aObject.ClassType = VMT.SelfPtr) then Result := True; end; Gruß Hawkeye |
Re: Überprüfen, ob ein Pointer auf ein Objekt zeigt
Vielen Dank für Eure Antworten - leider habe ich mir sowas schon gedacht...
Natürlich ist der Hinweis, die Verwaltung der Objekte von der der Zeiger zu trennen völlig richtig - das Problem ist, dass ich hier ein ziemlich altes und krudes Projekt bearbeiten muss und mir gedacht habe, dass ich mit der neuen Liste da etwas Ordnung schaffen könnte...war wohl nix. Gruß Frank |
Re: Überprüfen, ob ein Pointer auf ein Objekt zeigt
Zitat:
Objekte dieses Typs können dann leicht mit is erkannt werden.
Delphi-Quellcode:
Viele Grüße,
TMyPointerHolder = class
private FP: Pointer; public property P: Pointer read FP write FP; end; |
Re: Überprüfen, ob ein Pointer auf ein Objekt zeigt
@General: ich konnte es mir auch nicht verkneifen :oops:
Delphi-Quellcode:
Gut, IsValidObject hat duch mehr Abfragen eine höhere Wahrscheinlichkeit, daß es richtig liegt,
var x: Array[0..100] of Integer;
P: PInteger; begin X[30] := $6d696807; X[31] := $75737469; X[40] := Integer(@X[30]); X[51] := Integer(@X[51]); P := @X[51]; if PointsToObj(P) then ShowMessage('Ja, ich bin eine Klasse, und mein Klassenname ist "' + TObject(P).ClassName + '"'); if not IsValidObject(TObject(P)) then ShowMessage('Ich bin zwar zufällig kein valides Object, ' + 'aber das kann man leicht ändern *grins*'); aber dennoch kann es immernoch mal falsch liegen. ;) Nein, ich bin nicht so sehr selbstverliebt, aber dieser Name paßte nunmal zufällig genau rein :angel2: (und ich verrate nicht, was ich mit diesem Satz meine ... wer es gesehn hat, der weiß es) [add] so, der obere Code funktioniert mit D7 und wer weiß womit sonst noch, so wie ich es will ... ansonsten funktioniert er zwar, aber der Name gefällt mir nicht ... drum hier noch 'ne etwas angepaßtere Version der and
Delphi-Quellcode:
var x: Array[0..100] of Integer;
P: PInteger; i: Integer; begin i := 40 - vmtClassName shr 2; X[30] := $6d696807; X[31] := $75737469; X[40] := Integer(@X[30]); X[ i] := Integer(@X[ i]); P := @X[i]; if PointsToObj(P) then ShowMessage('Ja, ich bin eine Klasse, und mein Klassenname ist "' + TObject(P).ClassName + '"'); //if not IsValidObject(TObject(P)) then // ShowMessage('Ich bin zwar zufällig kein valides Object, ' // + 'aber das kann man leicht ändern *grins*'); end; |
Re: Überprüfen, ob ein Pointer auf ein Objekt zeigt
Ich würde das Problem so angehen:
Delphi-Quellcode:
TMyList = class (TObjectList)
constructor Create; public {...} end; constructor TMyList.Create; begin inherited; OwnsObjects := False; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:26 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-2025 by Thomas Breitkreuz