2016-04-10 12 views
1

Warum ist es nicht möglich, einen C++ - Dekompiler zu erstellen, der so genau funktioniert wie für Java und C#?Warum gibt es keinen genauen C++ - Decompiler?

+1

Eine sehr gute Frage. Nachdem Sie untersucht und verstanden haben, wie C++ in Maschinencode kompiliert wird und wie Java funktioniert, sollten Sie in der Lage sein, eine ziemlich gute Vorstellung von den Gründen zu haben. –

+0

Ich denke der Hauptgrund ist, dass C++ keine Laufzeit-Reflektionsmechanismen bereitstellt. –

+0

Nach allem, was wir gesehen haben, wie ist diese Frage und Antwort noch kein Duplikat? – Drop

Antwort

8

Es gibt mehrere Gründe:

  1. Inlining. In optimierten Builds wird viel C++ - Code eingebunden. Das spielt bei jeder Art von Decompiler eine Rolle. Um herauszufinden, dass eine Funktion inline ist, müsste der Decompiler die Spezifika des Inline-Codes analysieren und abgleichen. Und Post-Inlining-Optimierungsschritte können Code sehr unterschiedlich machen, abhängig davon, wo er inlined war.

  2. Vorlagen. Vorlagen verwenden ausschließlich # 1, verursachen aber zusätzliche Probleme. Es ist zumindest theoretisch möglich, dass eine Funktion, die an zwei Stellen inline wird, zu der gleichen Sequenz von Assemblerbefehlen kompiliert wird. Aber für Vorlagencode, der mit verschiedenen Vorlagenargumenten instanziiert wurde? Verschiedene Instanziierungen müssen normalerweise auf verschiedene Anweisungsfolgen kompiliert werden. Und dies wird noch schwieriger, da der Vorlagencode verschiedene Funktionen basierend auf den Vorlagenparametern aufrufen kann. Und diese Funktionen selbst könnten inline sein.

  3. Kompilierzeitausführung. Template-Metaprogrammierung ermöglicht dem Compiler, Code tatsächlich auszuführen. Aber C++ 11's constexpr bietet eine natürlichere Möglichkeit, einige Berechnungen zur Kompilierzeit durchzuführen. Offensichtlich können Kompilierungsfunktionsaufrufe oder Metafunktionsinstanziierungen nicht Teil der kompilierten ausführbaren Datei sein. Nur die Ergebnisse von ihnen werden (da ist das ein bisschen der Punkt).

  4. Fehlende umfassende Laufzeitreflexion. C# und Java schneiden ihren Bytecode mit vielen Informationen über die Art des ursprünglichen Quellcodes ab. Objektdefinitionen sind leicht erkennbar, ebenso wie Objektnamen, Elementvariablentypen und -namen usw. C++ kompiliert bis zur Maschinensprache, die keine solchen Informationen benötigt. Und da es nicht erforderlich ist, erzeugen Compiler es nicht. Sogar die Reflexionsstudiegruppe des ISO C++ Komitees konzentriert sich auf Kompilierungszeit Reflexion, die Informationen sind, die zur Laufzeit nicht verfügbar sein werden.

    Auch std::type_info bietet nichts. Wenn der Compiler nicht erkennt, dass ein bestimmter Typ typeid aufgerufen hat, muss der Compiler kein std::type_info Objekt dafür generieren. Und selbst wenn, dann ist alles, was Sie geben, der Name eines Objekts (und ein Bezeichner). Nichts mehr.

4

Da C++ - Compiler im Allgemeinen keine weiteren Informationen in die ausführbare Datei schreiben, als sie unbedingt benötigen (insbesondere nicht, wenn sie im Veröffentlichungsmodus kompiliert werden), müssen Sie die Informationen genau dekompilieren Programm ist einfach nicht in der ausführbaren Datei vorhanden.

Natürlich könnte ein C++ - Compiler erstellt werden, der alle notwendigen Informationen in der ausführbaren Datei enthält (z. B. in der naivsten Implementierung könnte er einfach eine Kopie des Quellcodes selbst in die ausführbare Datei einschließen), tut dies aber würde die ausführbaren Dateien erheblich größer machen, und die meisten nicht-Open-Source-C++ - Entwickler würden es bevorzugen, dass andere Leute nicht in der Lage sein, die ausführbare Datei zu dekompilieren, so dass es nicht eine ganze Menge Nachfrage für diese Funktionalität gibt.