8
votes

"Mélanger une bibliothèque de dll Boost avec un runtime statique est une très mauvaise idée ..."

J'ai deux projets dans une solution Visual Studio. On construit une LIB statique, l'autre construit une DLL dynamique. Utilisez les deux liaisons d'exécution statiques (/ mt et / mtd) et utilisent les deux boost. Boost n'a pas été ma décision - je voulais le demander, mais j'ai été annulé par le comité.

La LIB construit bien, mais la DLL touche une erreur de Auto_Link.hpp (ligne 354): "Mélangez une bibliothèque de Boost de DLL avec un Statique Runtime est une très mauvaise idée ... ". P>

#if (defined(_DLL) || defined(_RTLDLL)) && defined(BOOST_DYN_LINK)
#  define BOOST_LIB_PREFIX
#elif defined(BOOST_DYN_LINK)
#  error "Mixing a dll boost library with a static runtime is a really bad idea..."
#else
#  define BOOST_LIB_PREFIX "lib"
#endif


12 commentaires

Pouvez-vous simplement supprimer le chèque incriminé de Auto_Link.HPP? Ou #undef _usrdll et _windll avant auto_link.hpp est inclus, puis redéfinissez-les ensuite?


Je viens de traiter cela il y a quelques semaines, même si je ne me souviens pas des détails du sommet de ma tête. Nous avons une DLL qui est construite contre le Static CRT et Static Boost et il n'y a pas d'erreurs / avertissements. Je vais vérifier demain si personne ne répond à ce moment-là.


Il convient de noter que c'est extrêmement dangereux pour construire une DLL de manière statique à la bibliothèque d'exécution C. Ce que cela signifie que la mémoire allouée dans une DLL ne peut pas être directement libérée dans une autre. Cela peut sembler comme ça ne se produira pas, mais cela peut. Et vous obtiendrez des accidents aléatoires.


Cela ne s'applique pas uniquement au CRT statique. Vous avez le même problème si vous utilisez des dlls liés à différentes versions du CRT dynamique.


L'un de vos paramètres de projet doit être éteint. Nous avons une DLL qui est construite contre le CRT statique et le boost statique et ne pas avoir ce problème. Nous n'avons aucune déclaration spéciale #define ni quoi que ce soit. Le projet est une DLL avec _USRDLL (pas _dll) défini et exécuté à / mt.


Je connais cette configuration (un projet DLL en liaison avec Static Boost + Static CRT) est possible car je l'utilise moi-même. Je suggérerais de créer un nouveau projet de DLL minimaliste à partir de zéro et de faire fonctionner les trucs de boost. Comparez ensuite ce fichier de projet à votre problématique et voyez quelles sont les différences.


Il peut être utile de localiser le point auquel BOOST_DYN_LINK est défini. Cette erreur est-elle survenant lors de la compilation d'un ou de plusieurs des fichiers source de boost ou lors de la compilation de l'un de vos fichiers source via un #include?


Vous pouvez essayer de définir _DLL via les paramètres du projet, en préprocesseur sous C / C ++. Les en-têtes Windows ne semblent pas porter une attention à cette définition. Il pourrait donc ne pas avoir d'effets secondaires indésirables.


@noLoader: Le problème semble être que boost_dyn_link est défini quelque part. Je pense que vous devriez trouver où il est défini parce que je ne pense pas que ce soit. Si j'essaie de construire l'exemple minimal donné dans votre rapport de bogue (la regex) avec / mtd et de construire en tant que .dll, il semble fonctionner simplement (comme le gars de boost a dit). Avez-vous essayé de construire cet exemple minimal?


"Le problème semble être que boost_dyn_link est défini quelque part" - merci N1CKP. J'ai essayé de dire aux gens à booster aussi. Ils ont insisté sur je l'ai défini.


Je sais que cela fait quelques années de retard - mais cela peut aider si vous pouvez mettre à jour la question posée (en particulier la réponse incorrecte ci-dessous), elle est définie automatiquement par Boost-Python, quels que soient les autres paramètres utilisateur - à moins que l'utilisateur définit "boost_python_static_lib". C'est toujours un problème avec Boost dans la version 1.58


Peut-être que connexe: programmeurs.stackexchange.com/questions/262195/...


3 Réponses :


32
votes

Version courte: Écoutez les gars sur le boost ml. Boost ne supporte pas ce que vous essayez de faire, et c'est une mauvaise idée de toute façon. Mieux pour accepter cela et rendre l'autre bibliothèque utilise le temps d'exécution dynamique.

Version plus longue:

Vous semblez avoir mal compris ce que Boost vous dit. Vous essayez d'analyser le code source de boost au lieu de simplement lire ce qu'il dit:

AUTO_LINK.HPP (ligne 354): "Mélanger une bibliothèque de dll Boost avec un runtime statique est une très mauvaise idée ...".

Boost pense que vous construisez une DLL, tout en reliant simultanément de manière statique aux bibliothèques d'exécution. Ce qui est exactement ce que vous faites; Boost a détecté avec précision ce que vous essayez de faire.

Votre problème est que la bibliothèque de boost ne prend pas intégrée à une DLL qui ne relie pas dynamiquement aux bibliothèques d'exécution. La raison en est que c'est "une très mauvaise idée". Ils vérifient donc si vous essayez de le faire et d'arrêter votre construction avec un message d'erreur vous rappelant de ce fait.

Les "Freeards" à Boost qui ne savent pas comment faire quelque chose de travail "hors de la boîte" l'empêchent d'empêcher cela car la liaison statique à l'heure d'exécution dans une DLL est généralement une erreur de l'utilisateur. Il est soit fait accidentellement ou par ignorance des principaux problèmes que cela peut créer.

Si vous liez stagnalement sur les roulements, chaque DLL / EXE aura sa propre copie des runtimes, avec leurs propres variables globales. Et puisque le tas est géré via des globaux, cela signifie que chaque DLL / EXE aura son propre tas. Donc, si vous essayez de libérer la mémoire allouée dans un autre espace d'adresse ... BOOM. Et c'est beaucoup plus facile que vous ne le pensez si vous n'êtes pas prudent.

Cela peut aussi causer d'autres problèmes. Les "frisards" essaient de vous empêcher de vous tirer dessus dans le pied. Mais évidemment, vous savez mieux que de «forcer leur merde sur des utilisateurs honnêtes et sans méfiance» qui pourraient vouloir être conseillés quand ils sont sur le point de conduire sur une falaise.

Maintenant, vous pouvez simplement supprimer le message d'erreur. La plupart des boost sont des en-têtes, de sorte que vous ne reliez pas réellement à aucun de ses .libs, vous devriez aller bien. Cependant, je suppose que "auto_link.hpp" n'est utilisé que par les parties de boost qui sont des .Libs, les chances sont bonnes que le fait que vous avez rencontré pour commencer avec signifie que vous essayez de créer un lien vers un boost.

Modification de la liaison dynamique d'exécution (/ MD et / MDD) n'est pas réalisable car la liaison statique a été choisie (1) en raison des considérations de sécurité et (2) une autre bibliothèque utilise une liaison statique.

Si la sécurité est une considération, vous devez en être conscient: le fait même que vous construisez une DLL signifie que votre application est potentiellement ouverte aux injections de la DLL, quelle que soit la manière dont vous avez un lien vers les roulements. Donc, je ne vois pas comment la liaison dynamique n'est pas moins sécurisée que statique.


17 commentaires

Je ne pense pas que cela a raison. auto_link.hpp vérifie la vérification de _dll défini en fonction de ce que vous êtes en train de relier, et non du type de projet que vous construisez. Boost est livré avec des versions pré-construites de ses bibliothèques qui relient avec le CRT statique; Nous les utilisons dans une DLL juste bien. De toute évidence, nous n'utilisons pas les classes de boost dans l'interface de la DLL pour les raisons que vous avez énoncées.


@Luke: Peu importe ce que sont les #defines; L'erreur qu'il obtient exactement correspond à ce qu'il dit qu'il construit sa DLL. Le message d'erreur de boost indique qu'il ne peut pas construire une DLL de cette façon.


Bien sûr, le définir la matière; C'est ce que le message d'erreur est basé sur. Je conviens que certaines options de configuration sont incorrectes quelque part, mais il est possible de créer dans la configuration décrite dans la question initiale. Boost Ships binaires dans plusieurs configurations, dont l'un est boost comme une libération statique qui relie le CRT statique. Nous locions cela dans une DLL sans problème.


Pourquoi y avoir-il un problème avec le tas? Les fonctions de tas dans la bibliothèque d'exécution C appellent-elles simplement les fonctions Windows Heap?


@Harryjohnston: Les fonctions Windows Teasks renvoient des blocs de mémoire de la tailles de la page. Donc, les fonctions de démarrage d'exécution doivent diviser les blocs de la mémoire à votre application, la gestion de la mémoire à une granularité plus fine que 4 Ko.


@nicol: Non, les fonctions de tas de Windows ne renvoient pas les blocs de taille de page. Vérifiez la documentation ou essayez-la vous-même.


@Harryjohnston Quand dites "le tas", vous faites l'hypothèse qu'il n'y a qu'un seul tas. Il y a plusieurs tas et chaque instance de l'exécution C crée son tas - et c'est le problème.


@ shf301: Je n'ai pas regardé le code de l'exécution, alors je ne peux donc pas dire que vous vous trompez, mais pourquoi ne serait-ce pas simplement utiliser le tas de processus par défaut?


Anyhoo ... Si le comportement impair de MS C Runtime est un problème, cela pourrait être une alternative sensible: benshoof.org/blog/minicrt


"Boost pense que vous construisez une DLL, tout en reliant simultanément de manière statique aux bibliothèques d'exécution. C'est exactement ce que vous faites; Boost a détecté avec précision ce que vous essayez de faire." - Je n'essaie pas d'utiliser une dll de boost. Je construis une DLL, et je veux importer Boost comme une libération statique (comme toutes les autres bibliothèques que j'utilise).


@NoLoader: Ni I ni Boost, vous avez dit que vous utilisiez Boost comme DLL. Vous êtes bâtiment une DLL.


"DLL Boost Bibliothèque" - Qu'est-ce que cela signifie pour vous?


"Les" frisards "à Boost qui ne savent pas comment faire quelque chose de travail" hors de la boîte "l'empêchent d'empêcher cela car la liaison statique au runtime dans une DLL est généralement une erreur de l'utilisateur." - Les considérations de sécurité vont bien au-delà de la plantation binaire. Ce logiciel pourrait être certifié Certifié à un moment donné. Notre bibliothèque de sortie doit une DLL pour appliquer une limite de sécurité. Selon le laboratoire d'essai, ils peuvent (ou non) insister sur la liaison statique.


@noLoader: Vous m'avez curieux maintenant. Dans quel sens une DLL une limite de sécurité? (Un lien serait une réponse idéale.)


@Harry - voir FIPS 104-2 et FIPS 140-2 et Guide de mise en œuvre du CMVP . La DLL est la limite de module logique et ses méthodes exportées sont les interfaces pris en charge.


@noloader, si une DLL est préférée pour Boost, je ne vois pas pourquoi il n'est pas préféré pour la bibliothèque d'exécution C. Vous vous préparez à l'échec en insistant sur la configuration que vous avez choisie - les choses vont aller boom pour aucune raison explicable. C'est ce que l'erreur essaie de vous dire.


J'ai couru dans le même piège avec des tests unitaires; Github.com/triagens/arangodb/blob/master/unittest/ Les bases / ... exigent dynamique; Il semble que la cmake n'offre pas un moyen de mélanger la liaison statique et dynamique sous Windows? Il semble que les forfaits SF.NET ne fournissent pas statique, car après avoir reçu l'avertissement en commentant BOOST_TEST_DYN_LINK dans le fichier, cela compilerait, mais échoue pendant la liaison ... ou que je l'ai fait du mal?



12
votes

Ce problème est en effet une faute avec les paramètres de boosts. Pour une raison inconnue (que je ne peux pas déterminer pour être logique - comme cela n'a pas d'effet). Boost Python sera Forcer la liaison dynamique de boost, quelles que soient les options utilisateur

En bref, si vous avez Boost-Python dans votre projet, Boost empêche de manière incorrecte la liaison statique de boost avec le commutateur / MT.

Ce problème est résolu facilement en définissant boost_python_static_lib avant d'inclure les en-têtes de boost.


3 commentaires

Je vais accepter cela pour aider les futurs visiteurs parce que cela semble être une réponse raisonnable. Mais une mise en garde pour les futurs visiteurs: je n'ai pas pu la tester.


Pouvez-vous être précis sur ce que vous voulez dire comme définissant BOOST_PYTHON_STATICTATIC_LIB. Le chemin absolu de la bibliothèque? J'ai cette erreur et je ne peux pas sembler le casser. Juste une ligne d'exemple code?


@ bw4sz, tout avant, y compris l'en-tête Boost #define BOOSTT_PYTHON_PYTHON_PYTHON_STATICTATIC_LIB, ou définissez-le comme une définition de préprocesseur dans votre IDE / Makefile



0
votes

Je ne sais pas comment il a affecté la construction exactement, mais en cours d'exécution CUMAKE avec -DCMAKE_BUILD_TYPE = relase aidé. Probablement l'un des indicateurs mentionnés ici est une valeur par défaut pour la libération.


0 commentaires