Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Access Violation in TObject.InheritsFrom von "is"-Operator (https://www.delphipraxis.net/215454-access-violation-tobject-inheritsfrom-von-operator.html)

AuronTLG 5. Jul 2024 08:53

Access Violation in TObject.InheritsFrom von "is"-Operator
 
Moin,

ich habe hier gerade ein seltsames Problem, bei dem ich mal nachfragen wollte, ob das jemandem was sagt:
Ich hatte in Verbindung mit einer TMS-Komponente eine Zugriffsverletzung und hatte denen das mit einem sehr einfachen Testprojekt mitgeteilt. Dummerweise tritt bei denen das Problem partout nicht auf, was eine Lösung erschwert.

Debuggen liefert folgendes:
Die auslösende Codezeile ist eine einfache Klassenüberprüfung im Format "If (XYZ is TIchBinEineKlasse)". Von da aus geht es nach "System._IsClass" und von da aus zuguterletzt nach "System.TObject.InheritsFrom", wo es dann in der Codezeile "P := PPointer(@PByte(P)[vmtParent])^;" knallt.
Bevor es knallt ist das Programm aber schon einmal über besagte auslösende Codestelle problemlos drübergelaufen.
Und nur um das das Offensichtliche auszuschließen: "XYZ" ist kein Nullpointer.

Dementsprechend habe ich zwei Merkwürdigkeiten:

1. Dass es bei der Nutzung vom is-Operator überhaupt knallen kann. Es ist ja nicht so dass man dabei irgendwas falsch machen könnte.
2. Dass es nur bei mir auftritt. Wobei ich es sicherheitshalber auch nochmal auf einem anderen PC mit komplett eigener Kompilierung ebenfalls reproduzieren konnte.

Ich habe die neuste Delphi Version mit Patch, das neuste Windows 11, die neuste Komponentenversion und das Projekt in dem ich es reproduziere ist ein absolut jungfräuliches und minimalistisches Projekt ohne irgendwelche Einstellungsänderungen etc, d.h. auch da kann nichts schieflaufen. Ich kann mir auch nicht vorstellen, dass das irgendwie an einer allgemeinen Delphi-Einstellung hängen sollte, will es aber auch nicht ausschließen.

Hat irgendwer sowas schonmal gehabt?

jaenicke 5. Jul 2024 09:04

AW: Access Violation in TObject.InheritsFrom von "is"-Operator
 
Eine Möglichkeit ist, dass im Speicher etwas nicht in Ordnung ist, weil an anderer Stelle Speicher überschrieben wurde. Letzlich bleibt in solch einem Fall nur, den Speicherinhalt zu prüfen. Da sich die VMT nach dem ersten erfolgreichen Aufruf nicht ändern sollte, ist das in dem Fall überschaubar. Da kannst du den Speicherbereich vorher und nachher anschauen. Du kannst da auch mit Datenhaltepunkten arbeiten, damit du Änderungen mitbekommst.

Schlimmer ist es, wenn das nur in einem echten großen Projekt auftritt...

dummzeuch 5. Jul 2024 09:13

AW: Access Violation in TObject.InheritsFrom von "is"-Operator
 
Zitat:

Zitat von AuronTLG (Beitrag 1538613)
Und nur um das das Offensichtliche auszuschließen: "XYZ" ist kein Nullpointer.

Dementsprechend habe ich zwei Merkwürdigkeiten:

1. Dass es bei der Nutzung vom is-Operator überhaupt knallen kann. Es ist ja nicht so dass man dabei irgendwas falsch machen könnte.
2. Dass es nur bei mir auftritt. Wobei ich es sicherheitshalber auch nochmal auf einem anderen PC mit komplett eigener Kompilierung ebenfalls reproduzieren konnte.

Dass es kein NIL-Pointer ist, heißt nicht, dass es ein Pointer auf ein gültiges Objekt ist.

Folgendes knallt auch:
Delphi-Quellcode:
var
  SomeObj: TSomeClass;
begin
  SomeObj := Pointer(5);
  if SomeObj = nil then
    raise Exception.Create('SomeObj ist nil');
  if not (SomeObj is TSomeClass) then
    raise Exception.Create('SomeObj ist kein TSomeClass');
end;
Da $00000005 kein Pointer auf ein TObject ist, knallt es hier auch schon beim Ausführen des IS-Operators.

So einfach wird es in Deinem Fall aber wohl nicht sein, sondern eher sowas wie:

Delphi-Quellcode:

procedure DoSomething(var _Obj: TSomeClass);
begin
  _Obj.Free;
end;

var
  SomeObj: TSomeClass;
begin
  SomeObj := TSomeClass.Create;
  DoSomething(SomeObj);
  if SomeObj = nil then
    raise Exception.Create('SomeObj ist nil');
  if not (SomeObj is TSomeClass) then
    raise Exception.Create('SomeObj ist kein TSomeClass');
end;
Der Pointer zeigt nach Aufruf von DoSomething auf eine inzwischen freigegebene Instanz von TSomeClass. Je nachdem, ob der davon benutzte Speicher in der Zwischenzeit anderweitig verwendet wurde oder nicht, wird der IS-Operator fehlschlagen oder nicht. Ob das der Fall ist, kann von vielen Bedingungen abhängen. Und es kann sein, dass es auf einem Rechner zu einem Fehler führt und auf einem anderen nicht.

Es gibt auch noch andere Möglichkeiten (z.B. irgendwas übeschreibt den Pinter), aber ich dieser Fall ist der wahrscheinlichste.

jaenicke 5. Jul 2024 09:16

AW: Access Violation in TObject.InheritsFrom von "is"-Operator
 
Der Zugriff auf eine freigegebene Instanz kann mit FastMM sehr einfach erkannt werden. Bei einem einfachen Testprojekt sollte das aber normalerweise auch so auffallen.

Kannst du das Testprojekt hier zeigen?

himitsu 5. Jul 2024 09:20

AW: Access Violation in TObject.InheritsFrom von "is"-Operator
 
Während dieses Aufrufs wird der Speicher dort wohl nicht kaputt geh.

Es ist wohl eher so, dass es
* einfach ein ungültiger Zeiger ist -> Variable nicht initialisiert oder Objekt schon freigegeben, auf welches dort gezeigt wird
* oder es gab irgendwo z.B. einen Bufferoverflow und hat dir da was zerschossen.


Zu einem Zeitpunkt, wo es noch geht, müsstest du also anfangen und könntest dir dann die Speicher ansehen,
also die Stelle der Variable, bzw. den Inhalt des Objektes
* ganz am Anfang (Offset 0) steckt der Zeiger zur Klasse
* und dann in den Typinfos selbst, geht es dann weiter (vmtParent), da dort ja auch die Vorfahren geprüft werden

Das dann mit dem Zeitpunkt vergleichen, wenn es knallt,
und jetzt oder schon vorher prophylaktisch via Datenhaltepunkten, Guards oder ab und an manuell nachsehn, wann und durch wen es sich ändert.


Joar, das große FastMM im Debugmodus, Deleaker, Erekalog, madExcept und andere Tools können eventuell helfen.




"Testprojekt" oder selbst testen, also versuchen das im Kleinen nachzustellen,
bzw. das Projekt so lange ausmisten, bis der Fehler weg ist ... das zuletzt entfernte Codestück ist dann schonmal ein Anfang zum Suchen.



PS: Auch wenn es keine "wirkliche" Lösung ist, aber geh mal in Projektoptionen > Erzeugen > Delphi-Compiler > Linken > und schalte die beiden Optionen bezüglich ASLR ab .... ist der Fehler dann weg? :stupid:

AuronTLG 5. Jul 2024 09:42

AW: Access Violation in TObject.InheritsFrom von "is"-Operator
 
Zitat:

PS: Auch wenn es keine "wirkliche" Lösung ist, aber geh mal in Projektoptionen > Erzeugen > Delphi-Compiler > Linken > und schalte die beiden Optionen bezüglich ASLR ab .... ist der Fehler dann weg?
Nur schonmal schnelle Rückmeldung: Ohne ASLR-Unterstützung funktioniert es.
Ich schaue mir das Ganze genauer an, aber das ist schonmal ziemlich hilfreich zur Eingrenzung, danke.

himitsu 5. Jul 2024 10:19

AW: Access Violation in TObject.InheritsFrom von "is"-Operator
 
Eingrenzung nicht direkt.
ASLR sorgt ja nur dafür, dass DLLs und Speicheranforderungen mehr zufälliger verteilt werden.
z.B. auch DLLs in verschiedenen Prozessen nicht an der selben stelle liegen (wurde früher gern gemacht, damit Windows "identische" Teile des Speicher gemeinsam verwenden kann, bzw. z.B. Reallocationen nicht jedes mal neu berechnen muß, wenn im nächsten Prozess die selbe DLL geladen wird)

Wenn aber nun jemand mit statischen/hartcodierten Zeigern arbeitet, dann knallt es ... bzw. damit auch Hacker/Viren/Trojaner/usw. es schwerer haben.


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:33 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