Sie, wie Sie sagen compiler NICHT optimieren Sie bestimmte Codes entfernt?
Gibt es eine Möglichkeit, dem compiler (g++ in meinem Fall) nicht Optimierung bestimmter code entfernt, auch wenn der code nicht erreichbar ist? Ich möchte nur die Symbole in der Objekt-Datei.
Beispiel: Hier ist eine einfache Funktion, und ich will diese Funktion kompiliert werden, auch wenn es nie genannt.
void foo(){
Foo<int> v;
}
Wenn es keine offizielle compiler-Direktive, gibt es einen trick, um den compiler zu denken, dass es eine wichtige Funktion? Oder zumindest denke, dass es nicht ignoriert werden? Ich habe versucht, so etwas wie dieses:
extern bool bar;
void foo(){
if(bar){
Foo<int> v;
}
}
aber das hat nicht scheinen, es zu tun.
(Wenn Sie wirklich wissen wollen, warum ich auf der Erde wollen würde, - es hat zu tun mit diese Frage, wo, statt explizite template-Instantiierung mit template class Foo<int>
ich möchte einfach in der Lage sein, zu schreiben Foo<int> v
, da in vielen Fällen einfacher, da es implizit instanziiert alle Funktionen benötigt, und es funktioniert auch Prima in den debug-Modus ohne Optimierungen ...)
UPDATE:
Hier ist, was ich tun will (als kompilierbare mini-Beispiel):
foo.h (solche Dateien, die mir gegeben werden und nicht veränderbar)
template<class T>
struct Foo {
T val_;
Foo(T val) : val_(val) {
//heavy code, long compile times
}
};
foo-instantiation.cpp
#include "foo.h"
void neverCalled() {
Foo<int> f(1);
}
//The standard way to instantiate it is this:
//template class Foo<int>;
//but in reality it is often hard to find out
//exactly what types I have to declare.
//Usage like Foo<int> f(1); will instantiate all
//dependent types if necessary.
foo-decl.h (eine Schnittstelle, die ich extrahiert aus foo.h)
template<class T>
struct Foo {
T val_;
Foo(T val); //no heavy code, can include anywhere and compile fast
};
main.cpp
#include <iostream>
#include "foo-decl.h"
int main(int argc, char** argv){
Foo<int> foo(1);
return 0;
}
Zusammenstellung (keine Optimierung)
g++ -c main.cpp
g++ -c foo-instantiation.cpp
g++ main.o foo-instantiation.oo
Zusammenstellung (Optimierung)
g++ -O2 -c main.cpp
g++ -O2 -c foo-instantiation.cpp
g++ main.o foo-instantiation.oo
main.o(.text+0x13): In function `main':
: undefined reference to `Foo<int>::Foo(int)'
collect2: ld returned 1 exit status
- Ich habe versucht, vorkompilierte Header statt, aber die template-Instantiierung Methode macht wesentlich schnellere Zusammenstellung.
- Kompilieren
foo-instantiation.cpp
ohne Optimierung ist nicht so ideal, weil dann der code der Bibliothek (foo.h
und andere) langsamer.
InformationsquelleAutor Frank | 2009-03-20
Du musst angemeldet sein, um einen Kommentar abzugeben.
Werden Sie ausgeführt in die Eine-Definition-Regel. In einer Datei müssen Sie eine definition:
und in einem anderen eine andere definition:
Dies ist ausdrücklich nicht erlaubt, in C++ (nur eine identische definition erlaubt) und wenn du gegen die Regel, kann Ihr code gut zu funktionieren scheinen, manchmal, aber was Sie eigentlich haben, ist die gefürchtete "undefined behaviour" - nichts kann passieren je nach phase des Mondes (aber eher der innere Zustand der compiler in bestimmten kritischen Augenblicken).
Im Grunde, können Sie nicht den code schreiben, wie die - sorry.
dehmann, ich habe immer noch nicht verstanden, was der Teufel ist, besser mit Ihrem Weg zu tun, als bei der expliziten Instantiierung. beide haben die gleichen Nachteile, nicht wahr? (und bei dir ist zusätzlich zu undefiniertem Verhalten)
Es ist nicht ein ODR Verletzung problem. Der compiler ist eindeutig besagt, dass es keine definition der Klasse, nicht, dass es gibt mehrere. ODR Verletzungen mit Vorlagen ist ein heikles Thema, und ein Kommentar hat keinen Platz für eine vollständige Beschreibung, aber das ist nicht der Fall.
Eigentlich, wenn Sie ändern foo.h enthalten foo-decl.h und fügen Sie die definition der Funktion außerhalb der Klasse Körper, es funktioniert gut. (Aber das ist keine option für mich, da kann ich nicht ändern, alle meine foo.h-wie Dateien, es gibt zu viele von Ihnen, und ändern Sie ist zu gefährlich.)
InformationsquelleAutor
Den compiler nicht optimieren, die Funktion Körper Weg, ob Sie es erklären, extern oder nicht, weil es nicht weiß, dass die Funktion nicht aufgerufen wird, aus einer anderen compilation unit. Könnte es optimieren, es zu erreichen, wenn Sie erklärt, es statische, aber ich don t glaube, jeder Compiler tun das.
Den compiler kann optimieren entfernte Funktionsaufrufe:
In der vor dem Aufruf von foo() kann erstellte.
OTOH, die linker entfernen können Funktionskörper von der endgültigen excecutable, wenn Sie nicht abgerufen werden.
Für die oben genannten und anderen Gründen, die wir wirklich brauchen, um zu sehen, einige echte code, um Ihr problem diagnostizieren.
Eigentlich ja, der compiler kann sehen, dass Foo<int> v ist noch nie verwendet, und optimieren Sie es Weg.
post einige Beweis für diese Behauptung bitte
Wenn ich kompilieren, ohne Optimierung, die nm-tool zeigt 3 Symbole in foo-Instanzen.o: _Z11neverCalledv, _ZN3FooIiEC1Ei, __gxx_personality_v0. Aber wenn ich kompilieren mit -O2, es ist nur ein symbol: _Z11neverCalledv. So ...Foo... ist nicht mehr da.
Siehe mein Beitrag bezüglich der ODR
InformationsquelleAutor
suchen Sie in der Dokumentation unter dem Thema #pragma. Diese definieren, ist eine Art Flucht Luke, die Sie angeben können, alle Arten von Eigenschaften. gcc unterstützt, so dass es eine gute Wette, dass g++ wird als gut. Seien Sie gewarnt, dass dies wahrscheinlich nicht tragbar, die möglicherweise oder möglicherweise nicht von Bedeutung sein, für Ihr Projekt.
Habe ich erwähnt, dass Sie wahrscheinlich nicht tragbar und für einige Projekte ist dies kein Problem, ich weiß das, und ich sagte, als solche. Ich ließ es bis zu der Frage, die Befürworter, zu entscheiden, ob dies ist ein Mittel, das geeignet ist für Ihr Projekt
InformationsquelleAutor MikeJ
Ist der compiler die Optimierung entfernt eine variable, die nie benutzt wird, kann er nicht optimieren, eine Funktion, mit der Begründung, dass es nicht verwendet werden, da es verwendet werden könnte, aus einer anderen compilation unit. Sie könnten versuchen, es zu erzwingen, die der compiler in Anbetracht der Variablen verwendet, die mit so etwas wie:
Eine bessere Lösung wäre explizit instanziieren die Vorlage, wenn Sie es wollen:
Benutzer-code werden nur die header und wissen, welche Methoden vorhanden sind, aber nicht die tatsächliche Umsetzung. Die Umsetzung, zusammengestellt in einer compilation unit, wo die explizite template-Instantiierung erfolgt.
Beachten Sie, dass, wenn Sie vergessen, explizit instanziieren eines Typs, es wird ein linker-Fehler, nicht zu einem Kompilierungsfehler.
Die One Definition Rule
Die one definition rule in c++ besagt, dass es nur eine definition für jedes symbol oder Klasse. Mehrere Definitionen können leicht entdeckt werden, die für regelmäßige Symbole (wenn Sie definieren zwei
void f() { }
der linker erkennt das duplizierte symbol) aber ist ein wenig schwieriger, mit Vorlagen. Mit Vorlagen ist es schwieriger, denn Sie sind in der Regel deklariert und definiert, die in den header-Dateien. Der compiler generiert die Symbole verwendet, die in jeder compilation unit [1] und der linker findet in der Regel mehr als ein entspricht-symbol ( std::vector::push_back() kompiliert, die in jede compilation-unit, die hat einen std::vector und fordert push_back)Den compiler-flags der Vorlagen-code als 'schwach' symbol, was bedeutet, dass, während das symbol definiert ist hier, es kann auch definiert werden, in einer anderen compilation unit und der linker ist kostenlos entsorgen das symbol ohne, woraus sich ein link-Fehler. Das ist eine Voraussetzung, wenn Sie den link erstellen möchten anderen compilation-units, die mit der gleichen STL-Anlagen, zum Beispiel, mit den gleichen Typen.
Bis zu gcc-4.2, gcc-linux-linker verwirft alle, aber einer der schwachen Symbole ohne weitere Prüfung. Einige linkern (gcc-linker in linux wird in Naher Zukunft nicht als 4.2, weiß nicht 4.3 noch 4.4 könnte es bereits dort) zu tun, überprüfen Sie, dass die anderen 'schwachen' - Symbole sind in der Tat die gleiche und liefern eine Fehlermeldung/Warnung an den Benutzer.
Dein code ist brechen das ODR-in, dass Sie redeclaring die Vorlage in einem anderen Ort. Sie sollten erklären, die Vorlage einmal und die Methoden implementieren, die nach außen als oben gepostet. Jedenfalls, wenn beide Definitionen sind kompatibel (wie Sie in den snippet, das Sie gepostet): alle Mitgliedstaaten Methoden und Attribute sind genau die gleichen und mit der gleichen Qualifizierer (virtual/const-ness...) sollte es werden vom compiler akzeptiert, da es nur eine definition (leider wiederholt) von der Vorlage.
[1] Nur die Methoden, die tatsächlich aufgerufen werden, der code wird kompiliert:
InformationsquelleAutor David Rodríguez - dribeas
In der Regel erfolgt dies durch eine compiler-Direktive. In C wird es ein #pragma, und in Delphi-Pascal ist es mit {$O- }, {$O+} um den code in Frage. Die genaue syntax und Methode ist die Umsetzung spezifischer, so ist es eine Frage der überprüfung der Unterlagen für welches system Sie verwenden.
Nicht die Optimierung einer Funktion Weg ist sehr einfach, aber, einmal oder zweimal, ich habe Fälle gesehen, wo es notwendig gewesen ist, zu sagen, der compiler nicht optimieren spezifischen code. Dies ist extrem selten, und nicht etwas, das ich begegnet bin, für eine sehr lange Zeit, aber es kann gelegentlich passieren. Fälle, in denen es spielt sind in der Regel dort, wo man das kompilieren gegen einige alte legacy-code, die erstellt wurde, bevor eine spätere Entwicklung in der cpu-Technologie, Hyper-Threading-ein klassischer Fall, in point.
InformationsquelleAutor Cruachan
Weg von der hand, ich bin mir nicht sicher. Vielleicht Vorkompilierte Header wird dieses problem lösen?
Einfach, dies zu ändern ein bisschen, natürlich ist das nicht bei dem problem helfen zu können, verwenden Sie die kleinere template-header in deinem code, aber es könnte helfen, mit compile-Zeit-problem (und somit entfernen die Notwendigkeit für die Vorlage).
Tatsächlich, es kann "precompile". "Precompile" ist ein wenig irreführend, obwohl es ist mehr wie, "pre-analysieren und auswerten", als tatsächlich kompilieren. Der compiler kann immer noch alles tun, die Arbeit der übersetzung der template-code in seine eigene interne Darstellung einer Vorlage.
InformationsquelleAutor Bill Lynch
Deklarieren Sie Ihre Variablen als volatile:
In der Regel, es verhindert Optimierungen. Ich habe es mit dem Intel C++ - Compiler und Microsoft Visual Studio 2008.
InformationsquelleAutor Vladimir Obrizan