Je travaille sur une application C ++ qui utilise une bibliothèque écrite en C par une autre équipe. Les écrivains de la bibliothèque aiment appeler J'ai un code source complet pour l'application et la bibliothèque, mais la bibliothèque est très bien établie et n'a aucun test d'unité, ce qui changera que ce serait une grosse affaire. Existe-t-il un moyen de "accrocher" les appels vers Une possibilité que je envisage de faire une grande classe qui est em> l'application - c'est-à-dire que tout nettoyage se produirait soit dans son destructeur, soit dans le destructeur de l'un de ses membres - alors allouant l'une de ces gros objets sur le tas dans Y a-t-il un bon moyen connu d'aborder ce problème? P> quitter () code> lorsque les erreurs se produisent, ce qui finit le programme immédiatement sans appeler les destructeurs d'objets sur la pile dans l'application C ++. L'application définit certaines ressources système qui ne sont pas automatiquement récupérées par le système d'exploitation après la fin du processus (régions de mémoire partagées, mutiles interprocesses, etc.), c'est donc un problème. p>
sortie () code> afin que je puisse mettre en œuvre l'arrêt gracieux pour mon application? p>
Main () code>, définir un pointeur global pour le pointer et utiliser
atexit () code> pour enregistrer un gestionnaire qui supprime simplement l'objet via le global aiguille. Est-ce que cela devrait fonctionner? p>
4 Réponses :
Dans le même cas, vous pouvez toujours écrire votre propre implémentation de Puisque vous avez la source de la bibliothèque, il est encore plus facile - il suffit d'ajouter un drapeau Quitter code> et le lier plutôt que la propre implémentation du système. Vous pouvez gérer les erreurs là-bas et appeler éventuellement
_exit (2) code> A> vous-même. p>
-dexit = myexit code> lorsque vous le construisez, puis fournissez une implémentation de
myexit code>. p>
Aha! Le maquillage de l'application C ++ peut simplement redéfinir Quitter code> lors de la compilation de la bibliothèque C - aucune nécessité de modifier le code du tout. Je devrai encore implémenter la possibilité de nettoyer toute l'application d'un gestionnaire mondial, mais c'est toujours la meilleure réponse jusqu'à présent.
Hey, j'essaie de le faire maintenant sur une machine Linux, en utilisant -dexit = myexit code> mais malheureusement, je rencontre cette erreur:
dans le fichier inclus de / usr / include / c ++ / 7 /ext/string_conversions.h:41:0, de /usr/include/c++/7/bits/basic_string.h:6352, à partir de /usr/include/c++/7/string:52.../usr/include/ C ++ / 7 / CSTDLIB: 14 6:11: Erreur: ':: sortie' n'a pas été déclaré à l'aide de :: sortie; code> Avez-vous des idées pour un correctif? Publié à: Stackoverflow.com/questions/53531550/... < / a>
Installer le gestionnaire de sortie avec Atexit et implémenter le comportement souhaité p>
J'ai pensé à cela (c'est dans la question). Le problème est que les variables locales de chaque fonction de la pile d'appel ne sont pas disponibles à un simple gestionnaire - d'où mes pensées sur la création de l'application elle-même un seul objet attribué sur le tas et supprimables via un pointeur global.
Si vous souhaitez rendre la bibliothèque C plus utilisable de C ++, vous pouvez peut-être l'exécuter dans un processus distinct. Assurez-vous ensuite (avec un gestionnaire de sortie ou autrement) que lorsqu'il sort, votre processus d'application principal notit et jette une exception pour dérouler sa propre pile. Peut-être dans certains cas, il pourrait gérer l'erreur d'une manière non mortelle. P>
Bien entendu, déplacer l'utilisation de la bibliothèque dans un autre processus pourrait ne pas être facile ou particulièrement efficace. Vous aurez du travail à faire pour envelopper l'interface et de copier des entrées et des sorties via le mécanisme IPC de votre choix. P>
En tant que solution de contournement pour utiliser la bibliothèque à partir de votre processus principal, je pense que celui que vous décrivez devrait fonctionner. Le risque est que vous ne pouvez pas identifier et isoler tout ce qui nécessite de nettoyer, ou que quelqu'un à l'avenir modifie votre application (ou un autre composant que vous utilisez) sur l'hypothèse que la pile sera déroutée normalement. P>
vous pourrait em> modifier la source de la bibliothèque pour appeler une fonction d'exécution ou de la compilée-configurable au lieu d'appeler sortie () code>. Ensuite, compilez la bibliothèque avec une manipulation d'exception et implémentez la fonction en C ++ pour lancer une exception. Le problème avec c'est que la bibliothèque elle-même modifie probablement des ressources sur l'erreur, vous devez donc utiliser cette exception seulement em> pour dérouler la pile (et peut-être faire des rapports d'erreur). Ne l'attrapez pas et continuez même si l'erreur pourrait être non mortelle aussi fatale que votre application est concernée. P>
Si l'appel Si tout le reste échoue, car vous avez la source de la bibliothèque, vous pouvez lire des astuces macro pour remplacer efficacement les appels à EXIT code> et non
affirmez code> ou
Abandon code>, il y a quelques points pour obtenir un contrôle à nouveau: P>
Quitter code>, les destructeurs des objets avec une durée de vie statique (essentiellement: globaux et objets déclarés avec
statique code>) sont toujours exécutés. Cela signifie que vous pouvez configurer un (quelques) objet (s) mondial (s) de «gestionnaire de ressources» et publier les ressources dans leur (s) destructeur (s). LI>
atexit code>. Cela ne se limite pas à un. Vous pouvez vous inscrire plus. LI>
ul>
Quitter code> avec une fonction de votre choix qui pourrait, par exemple, lancer une exception. p>