2014-12-22 1 views
7

Beim Modding eines Closed-Source-Spiels modifiziere ich den Maschinencode zur Laufzeit zu jmp in meinen eigenen Code. Um dies auf generische Weise zu tun, verwende ich den Mustervergleich, um die Code-Orte zu finden, die ich ändern möchte. (Die Muster bestehen nur aus Zeichen/Bytes und Platzhaltern, wo Bytes variieren können.) Indem ich einen deterministischen endlichen Automaten aus all meinen Mustern erstelle, kann ich in linearer Zeit suchen.kann der Compiler möglicherweise eine DFA aus einem regulären Ausdruck berechnen?

Allerdings habe ich festgestellt, dass die Erstellung des DFA mehr Zeit in Anspruch nimmt als tatsächlich ausgeführt wird, vor allem in Debug-Builds (die ich während der Entwicklung natürlich will), und das wird nur schlimmer, wenn ich weitere Muster hinzufüge. Aber das könnte offline einfach gemacht werden. Ich denke gerade über das Wie nach; kann der Compiler das tun?

Soweit ich weiß, ist es unmöglich mit constexpr Funktionen, da ich nicht mit ihnen statischen Speicher zuordnen kann. Aber ich habe das vage Gefühl, dass es mit Template-Metaprogrammierung typsicher sein sollte. Oder bin ich wahrscheinlich bei der Erstellung von Automaten mit Hunderten oder Tausenden von Zuständen auf Rekursionslimits gestoßen?

Und unabhängig von technischen Möglichkeiten, ist es sinnvoll? Oder sollte ich lieber eine Quelldatei in einem separaten Build-Schritt berechnen?

+5

Eine andere Sache zu beachten: Sie möchten vielleicht das DFA für die Regexp mit benutzerdefinierten Tool erstellen Sie schreiben und serialisieren es in eine Binärdatei. Zur Laufzeit müssen Sie das DFA nur importieren, anstatt es von Grund auf neu zu erstellen. Es sollte schneller als nur das Erstellen des DFA in Runtime sein. – bialpio

+1

Ich schätze, ich bin einfach ignorant, aber warum sollte ein DFA zur Kompilierungszeit erstellt werden, und wenn man seine Größe kennt, würde es eine Speicherzuweisung erfordern? Sicher, jede Konstruktion würde einen anderen Typ ergeben, aber das sollte kein Problem sein. Ich vermute, dass die Rekursionstiefe die wahrscheinlichere Einschränkung ist (obwohl ich nicht versucht habe, während der Kompilierung ein DFA zu erstellen). –

+4

Ich bin nicht sicher, ob es tatsächlich ein DFA oder ein NFA erzeugt, aber [Boost Xpressive] (http: //www.boost.org/doc/libs/1_57_0/doc/html/xpressive.html) (zumindest für ein Beispiel) konvertiert mindestens einen regulären Ausdruck in eine * gewisse * Art von FSM zur Kompilierzeit (und eine Anzahl anderer macht ähnliche Dinge) . –

Antwort

2

Ja, das ist möglich. Die Konstruktion kann mit einem der Standardalgorithmen wie Thompson's construction algorithm durchgeführt werden, um ein NFA zu erhalten und daraus ein DFA zu erstellen. Das Problem ist, dass bei der Umwandlung eines NFA in einen DFA ein exponentieller Anstieg der Anzahl der Zustände möglich ist.

Der Umgang mit der erforderlichen Rekursionstiefe wird in der answers to this question diskutiert.

Es ist möglich, den Algorithmus mithilfe von Template-Metaprogrammierung zu implementieren. Eine Liste der grundlegenden Bausteine ​​finden Sie unter here, in der Sie Werte speichern, Verzweigungen und Funktionen implementieren können. Hier

ist ein Beispiel für eine Funktion aus der linked page:

template<int X, int Y> 
struct Adder 
{ 
    enum { result = X + Y }; 
}; 

Dies ist eine Funktion, die seine beiden Parameter und speichert das Ergebnis in dem Ergebnis enum Element hinzufügt. Sie können dies zur Kompilierzeit mit so etwas wie Adder < 1, 2> :: result aufrufen, was bei kompiliert wird Zeit und genau wie ein Literal 3 in Ihrem Programm handeln.

Seit Thompson-Algorithmus beruht auf Rekursion, hier ein Beispiel für eine Rekursion Bewertung:

template <unsigned n> 
struct factorial 
{ 
    enum { value = n * factorial<n-1>::value }; 
}; 

Dieses eine faktorielle bei der Kompilierung implementiert. Dies könnte dann während der Laufzeit wie folgt verwendet werden factorial<5>::value.

+0

Ich verstehe einfach nicht, wie ich eine beliebig große Menge von Zuständen repräsentieren und berechnen würde, die in TMP aufeinander verweisen. Aber ich werde das wahrscheinlich nicht mit TMP machen, sondern das Ergebnis einer Online-Berechnung in einer Datei zwischenspeichern, das ist viel einfacher. –

Verwandte Themen