Visibilité des symboles et espace de noms
Je suis en train d'expérimenter avec C++ symbole de la visibilité sur Linux et gcc. Il semble que le meilleur moyen est d'utiliser -fvisibility=cachés, et d'exporter des symboles utilisés un par un en fonction de la Visibilité de gcc page wiki (http://gcc.gnu.org/wiki/Visibility).
Mon problème est que de nombreux bibliothèques ne gère pas bien, ils oublient explicitement exportation de symboles, ce qui est un grave problème. Après plusieurs corrections de bogues même certaines parties de boost peut encore être affectée. Bien sûr, ces bugs devrait être fixé, mais jusqu'à ce que je voudrais utiliser un "coffre-fort" façon de cacher autant que les symboles que possible.
J'ai trouvé une solution: je mets tous les symboles dans un espace de noms et j'utilise le symbole de cacher de l'attribut et de l'exportation de l'interface publique, de cette façon seulement mon symboles peuvent être affectés.
Le problème est que j'ai eu un message d'avertissement quand je compile quelque chose contre cette bibliothèque pour chaque classe que je n'ai pas exporté et que j'utilise dans l'application en tant que champ de la classe.
namespace MyDSO __attribute__ ((visibility ("hidden"))) {
struct Foo {
void bar() __attribute__ ((visibility ("default"))) {}
};
}
struct Bar {
MyDSO::Foo foo;
};
int main() {}
Le message d'avertissement peut être reproduit dans ce petit exemple, mais bien sûr l'espace de noms doit être dans une bibliothèque à l'autre classe de l'application.
$ gcc-4.7.1 namespace.cpp -o namespace
namespace.cpp:7:8: warning: ‘Bar’ declared with greater visibility than the type of its field ‘Bar::foo’ [-Wattributes]
Que je comprends symbole de la visibilité, de cacher l'espace de noms doit avoir assez effet similaire à l'aide d'-fvisibility=caché, mais je n'ai jamais eu des avertissements similaires à l'aide de ce dernier. Je vois que quand je passe la -fvisibility=masqué à la demande de la classe de l'application sera également caché, donc je ne vais pas obtenir un avertissement. Mais quand je ne passe pas l'option aucun des symboles dans les en-têtes semblent cachés pour le compilateur, donc je ne vais pas obtenir un avertissement de nouveau.
Qu'est-ce que le fait de proposer de ce message d'avertissement? Est-ce un problème grave? Dans quelles situations cela peut causer un problème? Comment cacher l'espace de noms différent de fvisibility=cachés?
source d'informationauteur VargaD
Vous devez vous connecter pour publier un commentaire.
Avant que je réponds à votre question, je dois mentionner que pour d'autres, la lecture que l'application de symbole attributs de visibilité par espace de noms est un GCC-fonctionnalité spécifique. MSVC prend uniquement en charge les dllexport sur les classes, variables et de fonctions, et si vous voulez que votre code soit portable, vous devez correspondre à MSVC. Comme mon GCC symbole de la visibilité guide (le lien sur le site web de GCC), MSVC de la macro en fonction dllexport machines peuvent être facilement réutilisés pour réaliser quelque chose de similaire sur GCC, de sorte que le portage de MSVC, vous obtiendrez symbole de la visibilité de la manipulation "gratuitement".
Au sujet de votre problème spécifique, GCC est correct pour vous en avertir. Si un utilisateur externe essayé d'utiliser du public de type Bar qu'ils ont presque certainement besoin d'utiliser tout ce qui est à l'intérieur de la Barre, y compris Bar::foo. Pour exactement la même raison, toutes les fonctions de membre, en dépit d'être privé, doivent être visibles. Beaucoup de gens sont surpris, le raisonnement que membre privé des symboles de fonction sont, par définition, inaccessible à toute personne, mais ils oublient que juste parce que le programmeur n'a pas accès ne signifie pas que le compilateur n'est pas besoin accès. En d'autres termes, privé des fonctions membres sont privés pour vous, mais pas le compilateur. Si elles apparaissent dans un fichier d'en-tête, qui généralement signifie que le compilateur a besoin de l'accès, même dans un espace de noms anonymes (qui ne sont anonymes, de programmeurs, de ne pas les compilateurs qui ont tendance à utiliser un hachage du contenu comme le "vrai" nom d'espace de noms).
Le masquage d'un espace de noms a des effets très différents à fvisibility=cachés. C'est parce que GCC vomit beaucoup de symboles au-dessus et au-delà de celles d'un type spécifique par exemple pour les vtables, pour type_info etc. -fvisibility=hidden cache des choses que vous ne pouvez pas masquer par un compilateur chargé chemin, et c'est des trucs absolument essentiel pour le chargement de deux fichiers binaires dans le même processus avec la collision des symboles, par exemple deux objets partagés construit à l'aide de différentes versions de Boost.
J'apprécie vos efforts pour résoudre les problèmes causés par la rupture de symbole de visibilité dans les ELF et les conséquences sur broken C++ binaires et bien perdu la productivité du programmeur. Cependant, vous ne pouvez pas fixer eux - ils sont des fautes dans ELFE lui-même, qui a été conçu pour C et pas du C++. Si c'est une consolation, j'ai écrit un interne BlackBerry livre blanc il y a quelques mois sur ce sujet comme ELF symbole de la visibilité des problèmes sont tout autant un problème pour nous dans BB10 comme ils le sont pour toute grande entreprise avec une importante base de code C++. Alors, peut-être que vous pourriez voir certaines des solutions proposées pour le C++17, surtout si Doug Gregor C++ Modules de mise en œuvre fait de bons progrès.
Votre utilisation des attributs de visibilité semble reculer pour moi; je pense que vous auriez de meilleurs résultats en utilisant -fvisibility=cachés et l'ajout de visibilité "par défaut" à la bibliothèque de la déclaration d'espace de noms, depuis l'interface de la bibliothèque a sans doute de visibilité par défaut ou vous ne pouvait pas l'utiliser à partir de votre application. Si vous ne voulez pas modifier les en-têtes de bibliothèque, vous pouvez utiliser la directive #pragma GCC visibilité push/pop autour de votre #comprend.
Aussi, comme Niall dit, le marquage individuel des fonctions de membre en tant que par défaut ne fonctionne pas, l'ensemble de Foo type doit avoir de la visibilité par défaut si c'est une partie de l'interface de la bibliothèque.