Frage

In meiner Anwendung habe ich ganz einige hohlraum Zeiger (dies wegen der historischen Gründen ist die Anwendung ursprünglich in reinem C geschrieben wurde). In einem meiner Module weiß ich, dass der hohlraum Zeiger verweisen auf Instanzen von Klassen, die von einer bekannten Basisklasse erben konnte, aber ich kann nicht 100% sicher davon sein. Daher könnte dabei eine dynamic_cast auf dem hohlraum Zeiger Probleme geben. Möglicherweise ist der hohlraum Zeiger selbst verweist auf eine Ebene-Struktur (also keine vptr in der Struktur).

Ich möchte die ersten 4 Bytes des Speichers untersuchen die hohlraum Zeiger zeigt auf, um zu sehen, ob dies die Adresse des gültigen VTable ist. Ich weiß, diese Plattform ist, vielleicht sogar Compiler-Version spezifisch, aber es könnte mir helfen, die Anwendung nach vorne in Bewegung und loszuwerden alle die hohlraum Zeiger über einen begrenzten Zeitraum (sagen wir mal 3 Jahre).

Gibt es eine Möglichkeit, eine Liste aller vtables in der Anwendung zu bekommen, oder eine Art und Weise, ob ein Zeiger auf eine gültige VTable zu überprüfen, und ob diese Instanz weist auf die VTable erbt von einer bekannten Basisklasse?

War es hilfreich?

Lösung

  

Ich möchte die erste untersuchen   4 Bytes des Speichers der hohlraum pointer   zeigen auf, um zu sehen, ob dies das ist   Adresse des gültigen VTable.

Sie können das tun, aber Sie haben keinerlei Gewähr, es wird funktionieren. Y weiß nicht einmal, wenn der void * auf die V-Tabelle verweisen. Zuletzt sah ich in diese (5 Jahre alt) ich einige Compiler den VTable-Zeiger vor die Adresse, auf die durch die Instanz *.

gespeichert glauben
  

ich weiß, ist diese Plattform, vielleicht sogar   Compiler-Version spezifisch,

Es kann auch Compiler-Optionen speciffic sein, je nachdem, welche Optimierungen Sie verwenden und so weiter.

  

, aber es könnte mir helfen, die bei der Bewegung   Anwendung nach vorn, und Loswerden   aller hohlraum Zeiger über ein   begrenzte Zeit (sagen wir mal 3   Jahre).

Ist dies die einzige Option, die Sie vorwärts zum Bewegen der Anwendung sehen? Haben Sie darüber nachgedacht andere?

  

Gibt es eine Möglichkeit, eine Liste aller zu erhalten   vtables in der Anwendung,

No: (

  

oder eine Art und Weise, ob ein Zeiger zu überprüfen   auf eine gültige VTable,

keine Standardmethode. Was können Sie tun, ist es, einige Klasse Zeiger in Ihrem Lieblings-Debugger öffnen (oder werfen den Speicher Bytes und melden Sie sich in einer Datei) und vergleichen Sie es und sehen, ob es Sinn macht. Trotzdem haben Sie keine Garantie, dass alle Ihre Daten (oder andere Hinweise in der Anwendung) nicht ähnlich genug aussehen (wenn sie gegossen als Bytes) zu verwechseln was auch immer Code, den Sie wie.

  

und ob diese Instanz weist auf   die vtable inherits aus einer bekannten Basis   Klasse?

Nein erneut.

Hier sind einige Fragen erhalten (die Sie bereits betrachtet haben können). Antworten auf diese können Ihnen mehr Möglichkeiten geben, oder geben Sie uns weitere Ideen vorschlagen:

  • Wie groß ist die Code-Basis? Ist es möglich, globale Veränderungen einzuführen, oder Funktionalität zu Spread-around für das?

  • haben Sie alle Zeiger gleichmäßig zu behandeln (dh: gibt es gemeinsame Punkte in Ihrem Quellcode, wo Sie in verstopfen könnten und die eigenen Metadaten hinzufügen)

  • Was können Sie in ihrem Quelltext ändern? (Wenn Sie den Zugriff auf Ihre Speicherzuweisung Subroutinen hat oder in Ihrem eigenen beispielsweise verstopfen könnten Sie möglicherweise in der Lage sein, in Ihrem eigenen Metadaten-Stecker).

  • Wenn verschiedene Datentypen void * in verschiedenen Teilen des Codes gegossen werden, wie Sie entscheiden, später, was in diesem Zeiger ist? Können Sie den Code, unterscheidet die void * verwenden, um zu entscheiden, ob sie Klassen sind oder nicht?

  • Gibt es in Ihrer Code-Basis für Refactoring Methoden erlauben? (Refactoring in kleinen Iterationen durch in alternativen Implementierungen für Teile des Codes anschließen, dann die erste Implementierung zu entfernen und testete alles)

Bearbeiten (vorgeschlagene Lösung):

Führen Sie die folgenden Schritte aus:

  • definiert eine Metadaten (Basis) Klasse

  • Ihre Allozierungsroutinen mit benutzerdefinierten diejenigen ersetzen, die dem Standard beziehen sich nur / alte Routinen (und stellen Sie sicher, dass Ihr Code funktioniert immer noch mit den benutzerdefinierten Routinen).

  • auf jeder Vergabe zuteilen the requested size + sizeof(Metadata*) (und stellen Sie sicher, dass Ihr Code funktioniert immer noch).

  • ersetzt die ersten sizeof(Metadata*) Ihre Zuordnung mit einem Standard-Byte-Sequenz-Bytes, dass man leicht Test für kann (ich bin teilweise zu 0xDEADBEEF: D). Kehrt dann [allocated address] + sizeof(Metadata*) an die Anwendung. Aufhebung der Zuordnung auf, nehmen den Zeiger empfangen, dekrementiert er durch `sizeof (Metadaten *), rufen dann die System / vorherigen Routine die Aufhebung der Zuordnung durchzuführen. Nun, Sie haben einen zusätzlichen Puffer im Code zugewiesen, die speziell für Metadaten zu jeder Zuordnung.

  • In den Fällen Sie in mit Metadaten für interessiert sind, erstellen / erhalten einen Metadatenklasse Zeiger, setzen sie dann in der 0xDEADBEEF Zone. wenn you müssen Metadaten, reinterpret_cast<Metadata*>([your void* here]) überprüfen, verringern sie, dann prüfen Sie, ob der Zeigerwert ist 0xDEADBEEF (keine Metadaten) oder etwas anderes.

Beachten Sie, dass dieser Code nur dort für Refactoring sein sollte - für die Produktion Code ist es langsam, fehleranfällig und generell andere schlechte Dinge, die Sie nicht wollen Ihre Produktion Code. Ich würde all dieser Code abhängig von einigen REFACTORING_SUPPORT_ENABLED Makro machen, die nie Ihre Metadaten Klasse das Licht einer Produktionsfreigabe zu sehen (außer bei der Prüfung baut vielleicht).

erlauben würde,

Andere Tipps

Ich würde sagen, dass es ohne zugehörige Referenz nicht möglich ist (Header-Deklaration).

Wenn Sie diese Leeren Zeiger auf korrekten Schnittstellentyp ersetzen wollen, hier ist das, was ich denke, es ist zu automatisieren:

  1. Gehen Sie durch Ihre Codebasis eine Liste aller Klassen zu erhalten, die virtuellen Funktionen hat, könnten Sie dies schnell tun, indem Skript zu schreiben, wie Perl

  2. Schreiben Sie eine Funktion, die einen void * Zeiger als Eingabe und Iterierte über diese Klassen versuchen, es zu dynamic_cast und Informationen protokollieren, wenn es gelungen, wie Interface-Typ, Codezeile

  3. Rufen Sie diese Funktion überall Sie void * Zeiger verwendet, vielleicht könnten Sie es mit einem Makro-wickeln, so dass Sie, Zeilen Informationen leicht erhalten könnte

  4. Führen Sie eine Automation (wenn vorhanden) und analysiert die Ausgabe.

Der einfachere Weg, um Überlastung operator new für Ihre Basisklasse sein würde. Auf diese Weise, wenn Sie Ihre void * Zeiger kennen zu Heap-Objekte, dann können Sie auch mit 100% iger Sicherheit festzustellen, ob sie zeigen auf Ihr Objekt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top