Comment dire le compilateur de ne PAS optimiser certains le code?
Est-il un moyen de dire au compilateur g++ dans mon cas) à pas optimiser certaines de code à distance, même si ce code n'est pas accessible? Je veux juste ces symboles dans le fichier d'objet.
Exemple: Ici est une simple fonction, et je ne veux que cette fonction soit compilé, même s'il n'est jamais appelé.
void foo(){
Foo<int> v;
}
Si il n'existe pas de directive du compilateur, est-il un truc pour faire le compilateur pense que c'est une fonction importante? Ou au moins lui faire croire qu'il ne peut pas être ignoré en toute sécurité? J'ai essayé quelque chose comme ceci:
extern bool bar;
void foo(){
if(bar){
Foo<int> v;
}
}
mais cela ne semblait pas le faire.
(Si vous voulez vraiment savoir pourquoi j'sur la terre ne souhaitez que -- qu'il a à faire avec cette question, où, au contraire explicite de l'instanciation d'un modèle avec template class Foo<int>
je veux simplement être en mesure d'écrire Foo<int> v
, puisque dans de nombreux cas, c'est plus facile car elle implicitement instancie toutes les fonctions nécessaires, et il fonctionne bien dans le mode de débogage sans optimisations ...)
Mise à JOUR:
Voici ce que je veux faire (comme un compilable mini exemple):
foo.h (ces fichiers sont donné à moi et non modifiables)
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 (une interface que j'ai extrait de 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;
}
Compilation (pas d'optimisation)
g++ -c main.cpp
g++ -c foo-instantiation.cpp
g++ main.o foo-instantiation.oo
Compilation (optimisation)
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
- J'ai essayé d'en-têtes précompilés à la place, mais l'instanciation du modèle de méthode permet d'accélérer la compilation.
- Compilation
foo-instantiation.cpp
sans optimisation n'est pas idéale, car alors le code de la bibliothèque (foo.h
et autres) vont s'exécuter plus lentement.
OriginalL'auteur Frank | 2009-03-20
Vous devez vous connecter pour publier un commentaire.
Vous êtes en cours d'exécution dans la Définition de la Règle. Dans un fichier que vous avez une définition:
et dans l'autre une définition différente:
Ce n'est pas explicitement autorisés en C++ (une seule définition identique permis) et si vous enfreignez la règle de votre code peut sembler à travailler parfois, mais ce que vous avez réellement est la fameuse "comportement indéfini" - n'importe quoi peut arriver, selon la phase de la lune (mais plus probablement de l'état interne du compilateur à certains moments critiques).
Fondamentalement, vous ne pouvez pas écrire un code comme celui - désolé.
dehmann, je n'ai toujours pas compris ce que le diable est mieux avec votre façon de le faire que de manière explicite de l'instanciation. les deux ont les mêmes inconvénients n'est-ce pas? (et le vôtre en plus c'est un comportement indéfini)
Ce n'est pas une ODR problème de violation. Le compilateur est clairement indiquer qu'il n'existe pas de définition de la classe, pas qu'il existe de multiples. ODR violations à l'aide de modèles est une question délicate, et un commentaire n'a pas d'espace pour une description complète, mais ce n'est pas le cas.
En fait, si vous changez de foo.h à inclure foo-decl.h et à ajouter la définition de la fonction à l'extérieur du corps de la classe, il fonctionne très bien. (Mais ce n'est pas une option pour moi, puisque je ne peux pas changer tous mes foo.h-comme pour les fichiers, il y a trop d'entre eux, et de les modifier est trop dangereux.)
OriginalL'auteur
La compilateur ne peut pas optimiser un corps de fonction de suite, si vous déclarez qu'il extern ou pas, car il ne peut pas savoir que la fonction n'est pas appelée à partir d'une autre unité de compilation. Il pourrait optimiser loin si vous avez déclaré il statique, mais je ne t en croire les compilateurs de faire ça.
Le compilateur peut optimiser loin des appels de fonction:
Au-dessus de l'appel à foo() peut être gommés.
Otoh, que, le de l'éditeur de liens peut supprimer la fonction des organes de la finale excecutable si ils ne sont pas appelés.
Pour ces raisons et d'autres, nous avons vraiment besoin de voir une partie de code réel afin de diagnostiquer votre problème.
En fait oui, le compilateur peut voir que les Foo<int> v n'est jamais utilisé et de l'optimiser à l'écart.
post la preuve de cette assertion, veuillez
Quand je compile sans optimisation, le nm outil montre 3 symboles foo-instanciations.o: _Z11neverCalledv, _ZN3FooIiEC1Ei, __gxx_la personnalité_v0. Mais quand je compile avec -O2, il n'y a qu'un seul symbole: _Z11neverCalledv. Alors ...Foo... n'existe plus.
Voir mon post concernant l'ODR
OriginalL'auteur
de recherche, de la documentation, sous la rubrique de #pragma. Ceci définit une sorte de sas de secours qui vous permet de spécifier toutes sortes de propriétés. gcc prend en charge, il y a donc fort à parier que g++. Soyez averti que ceux-ci sont susceptibles de ne pas portable qui peut ou ne peut pas être un souci pour votre projet.
Je l'ai mentionné qu'ils sont susceptibles de ne pas portable et pour certains projets, ce n'est pas un souci je le sais et je l'ai déclaré en tant que tel. Je l'ai laissé à la question promoteur de décider si c'est un moyen qui est approprié pour leur projet
OriginalL'auteur MikeJ
Le compilateur est l'optimisation de loin une variable qui n'est jamais utilisé, il ne peut pas optimiser une fonction au motif qu'il ne sera pas utilisé, car il pourrait être utilisé à partir d'une autre unité de compilation. Vous pouvez essayer de forcer le compilateur en considérant la variable utilisée avec quelque chose qui ressemble à:
Serait une meilleure solution pour instancier explicitement le modèle si vous le souhaitez:
Le code de l'utilisateur ne verra que les en-tête et de savoir quelles méthodes existent, mais pas la mise en œuvre réelle. La mise en œuvre seront compilées dans une unité de compilation, où l'explicite l'instanciation d'un modèle se produit.
Notez que si vous oubliez de les instancier explicitement un type, ce sera une erreur de l'éditeur de liens, pas d'erreur de compilation.
Une Définition De La Règle
Une définition de la règle en c++ états qu'il peut y avoir une seule définition pour chaque symbole ou de la classe. Le fait d'avoir plusieurs définitions peuvent être facilement détectés pour les symboles classiques (si vous définissez deux
void f() { }
l'éditeur de liens détecter le double symbole), mais est un peu plus délicat avec des modèles. Avec des modèles, il est plus difficile car ils sont généralement déclarées et définies dans les fichiers d'en-tête. Le compilateur génère les symboles utilisés dans chaque unité de compilation [1] et le linker les trouve souvent plus d'un symbole équivalent ( std::vector::push_back() est compilé dans chaque unité de compilation qui a un std::vector et des appels push_back)Les drapeaux du compilateur l'basées sur des modèles de code comme "faible", symbole, ce qui signifie que, tandis que le symbole est défini ici, elle peut également être définie dans une autre unité de compilation et de l'éditeur de liens est libre de jeter le symbole sans céder une erreur de lien. C'est une exigence si vous souhaitez lier les différentes unités de compilation qui font usage de la même STL installations, par exemple, avec les mêmes types.
Jusqu'à gcc 4.2, gcc linux de l'éditeur de liens ignore tout, mais la faiblesse des symboles sans autre vérification. Certains linkers (gcc éditeur de liens dans linux sera dans un futur proche, non pas comme 4.2, je ne sais pas 4.3 ni 4.4 il pourrait être déjà là) ne vérifier que les différents "faible", les symboles sont en fait les mêmes et fournir un message d'erreur/d'avertissement à l'utilisateur.
Votre code est rupture l'ODR en ce que vous êtes redeclaring le modèle dans un endroit différent. Vous devez déclarer le modèle une fois, et de mettre en œuvre les méthodes de l'extérieur comme affiché ci-dessus. De toute façon si les deux définitions sont compatibles (comme ils le sont dans l'extrait de code que vous avez posté): tous les membres de méthodes et d'attributs sont exactement les mêmes et avec les mêmes qualificatifs (virtuel/const-ness...), il doit être accepté par le compilateur comme il y a une seule définition de l'alas (répété) du modèle.
[1] Uniquement les méthodes qui sont appelés dans le code sera compilé:
OriginalL'auteur David Rodríguez - dribeas
Cela se fait généralement par une directive de compilation. En C, il sera un #pragma, et en Delphi Pascal c'est {$O- }, {$O+} le code en question. La syntaxe précise et la méthode de la mise en œuvre spécifique, c'est donc une question de vérification de la documentation de système que vous utilisez.
Pas l'optimisation d'une fonction de distance est assez simple, mais une fois ou deux fois j'ai vu des cas où il est nécessaire de dire au compilateur de ne pas optimiser le code. C'est extrêmement rares et pas quelque chose que j'ai trouver pour un temps très long, mais il peut arriver de temps en temps. Les cas où il ne sont en général où l'on est en train de compiler à l'encontre de certains vieux héritage de code qui a été construit avant un développement ultérieur processeur technologie hyperthreading d'être un cas classique en point.
OriginalL'auteur Cruachan
Hors part, je ne suis pas sûr. Peut-être Les en-têtes précompilés permettra de résoudre ce problème?
Juste à modifier un peu tout ça, évidemment, ce n'est pas aider avec le problème d'être en mesure d'utiliser le plus petit modèle d'en-tête dans votre code, mais il pourrait aider à la compilation problème de temps (et donc de supprimer la nécessité pour le modèle).
En fait, il peut "précompiler". "Précompiler" est un peu un abus de langage bien, c'est plus comme, "pré-analyser et d'évaluer de compiler. Le compilateur ne peut pas toujours faire tout le travail de traduction du code du modèle en son propre représentation interne d'un modèle.
OriginalL'auteur Bill Lynch
Déclarer votre variable volatile:
Généralement, il empêche toute optimisations. Je l'ai vérifié avec le Compilateur Intel C++ et Microsoft Visual Studio 2008.
OriginalL'auteur Vladimir Obrizan