Pointer auf Gültigkeit prüfen
-
Hallo zusammen,
ich habe bereits längere Zeit nach der Lösung eines Problems im Internet gesucht aber leider nichts gefunden, daher hoffe ich, dass ich hier erstens richtig bin und dass mir jemand helfen kann. Also folgendes:Ich habe eine Funktion, die einen Pointer auf eine Struktur übergeben bekommt. Mit diesem Pointer greife ich dann ganz normal auf die einzelnen Elemente der Struktur zu. Sieht in etwa so aus:
struct Eigenschaften {int größe}; void Funktion (Eigenschaften *e) { cout << e->größe << endl; }
Die Funktion wird allerdings nicht aus einer anderen Funktion heraus aufgerufen, sondern ist mit der Skriptsprache TCL/TK verknüpft. Dafür benutze ich die cpptcl-Bibliothek (was ich auch nicht ändern möchte^^). Ich kann jetzt also in eine Datei schreiben: Rufe mir bitte die Funktion auf (natürlich mit Angabe entsprechender Übergabeparameter), diese Datei dann zur Laufzeit auslesen und mit einem Interpreter diesen Code ausführen lassen (Was auch erstklassig funktioniert).
Aber genau bei der Übergabe liegt das Problem: Es kann dabei vorkommen, dass der Pointer der angegeben wird, nicht gültig ist, sprich gar nicht auf die gewünschte Struktur verweist sondern sonstwohin. Wenn dies passiert, stürzt mir das Programm natürlich sofort ab, wenn ich versuche auf ein Element der Struktur zuzugreifen.
Und diesen Fehler möchte ich abfangen, ich weiß nur leider nicht wie. Gibt es da vllt. Möglichkeiten den Pointer vor dem Zugriff auf Korrektheit zu überprüfen?
Also ob er wirklich auf eine gültige Struktur zeigt oder eben nicht?
Schon mal vielen Dank im VorrausMfG Mictlan
-
Mictlan schrieb:
Möglichkeiten den Pointer vor dem Zugriff auf Korrektheit zu überprüfen?
Nein.
-
Hmm schade. Aber danke für die schnelle Antwort.
-
Hmm. So direkt geht das nicht. Aber üblicherweise wird ein Zeiger, der nicht "gültig" ist auf 0 gesetzt, was du du dann abfragen kannst.
void Funktion (Eigenschaften *e) { if(!e) return; cout << e->größe << endl; }
-
Mictlan schrieb:
Es kann dabei vorkommen, dass der Pointer der angegeben wird, nicht gültig ist, sprich gar nicht auf die gewünschte Struktur verweist sondern sonstwohin.
du könntest als erstes member der struktur eine magische zahl hinterlegen und die dann vergleichen.
enum Objekttyp { typ_a = 0x0815 }; struct Eigenschaften { Objekttyp typ; int groesse; }; void Funktion (Eigenschaften *e) { if(e && reinterpret_cast<Objekttyp>(*e) == typ_a) cout << e->größe << endl; else cout << "nö!" << endl; }
ist aber sehr, sehr frickelig und funktioniert auch nur, wenn e auf ein objekt zeigt das noch existiert und mindestens sizeof(Objekttyp) groß ist. wenn der pointer wirklich *irgendwohin* zeigt, fliegt es dir sowieso um die ohren.
evtl. bietet das betriebsystem oder die rtl weitere möglichkeiten. aber wenn es irgendwie geht, solltest du solche hacks wirklich vermeiden. sorg lieber dafür, dass deine pointer gültig sind.
-
nekrovieh schrieb:
...
enum Objekttyp { typ_a = 0x0815 }; struct Eigenschaften { Objekttyp typ; int groesse; }; void Funktion (Eigenschaften *e) { if(e && reinterpret_cast<Objekttyp>(*e) == typ_a) cout << e->größe << endl; else cout << "nö!" << endl; }
...
DAS würde ich nicht machen, weil es mehr Sicherheit vorspiegelt als Du tatsächlich hast - z.B. weil ein Nichtinitialisierter Zeiger üblicherweise auch nicht auf 0 zeigt, sondern "irgendwohin" ... und da ist ein Zugriff mittels "reinterpret_cast" auch nicht sicherer/zuverlässiger/definierter als einer direkt auf "e->groesse".
(mal ganz davon abgesehen, dass der Hack auch nicht funktioniert, weil Eigenschaften::typ auch nicht initialisiert wird)Gruß,
Simon2.
-
Simon2 schrieb:
DAS würde ich nicht machen, weil es mehr Sicherheit vorspiegelt als Du tatsächlich hast - z.B. weil ein Nichtinitialisierter Zeiger üblicherweise auch nicht auf 0 zeigt, sondern "irgendwohin" ... und da ist ein Zugriff mittels "reinterpret_cast" auch nicht sicherer/zuverlässiger/definierter als einer direkt auf "e->groesse".
richtig. hatte ich ja auch dazugeschrieben. ich bin mal davon ausgegangen, dass das "irgendwo" des OP wenigstens ein gültiger speicherbereich ist.
(mal ganz davon abgesehen, dass der Hack auch nicht funktioniert, weil Eigenschaften::typ auch nicht initialisiert wird)
äh, ja. der konstruktor bzw. die zuweisung an typ fehlt noch, hab ich vergessen.
aber ein bisschen mitdenken kann man ja wohl erwarten. genauso gut könnte man sagen, dass der hack nicht funktioniert weil Funktion nicht aufgerufen wird.
-
nekrovieh schrieb:
...aber ein bisschen mitdenken kann man ja wohl erwarten. ...
Keine Sorge, das hatte ich auch getan (und mir war klar, dass Du den Konstruktoraufruf nur vergessen hattest) - deswegen hatte ich ja auch von diesem Argument "abgesehen" - ein Smiley von mir hätte da wohl Klarheit geschaffen. Sorry.
Letztlich ist das ein "isValid"-Flag mit all seinen und zusätzlichen Problemen (z.B. dass sich das Speicherlayout (z.B. für abgeleitete Objekte) verändern kann)....
Und es bleibt: Die schmalen Vorteile dieser Lösung sind IMHO den Aufwand nicht wert ... bzw. könnten Anwender sogar zu einer Sorglosigkeit verleiten, die die Gefahr eher erhöht.Gruß,
Simon2.
-
Ok ich danke für die Antworten.
Dann werde ich wohl versuchen müssen, die Fehlerquelle direkt abzuschalten. Hatte ja gehofft, dass ich das nicht machen müsste. Aber sauberer ist es natürlich auf jeden Fall. Ich hoffe nur, dass ich das irgendwie hinbekomme, Reverse Engineering an fremden Bibliotheken ist ja immer so eine Sache...thx Mictlan
-
WinAPI: IsBadReadPtr
Verifies that the calling process has read access to the specified range of memory.
Important This function is obsolete and should not be used.
-