Je travaille avec une bibliothèque C / FORTRAN à partir de C ++ et la sortie d'appels de la bibliothèque (). J'aimerais que cela jette une exception pour que les destructeurs de mon programme C ++ soient appelés. J'ai été en mesure de créer ma définition unique de sortie qui jette une exception, mais la terminaison est encore appelée. Est là pour empêcher d'être appelé d'être appelé et permettre la manipulation normale de l'exception?
Mise à jour: Dans les commentaires, il a été souligné que cela fonctionne sur X64 mais échoue sur x86, la question principale est donc "est donc une solution faire du x86 fonctionne comme x64? ". p>
update2: Voir ma réponse sur pourquoi cela ne fonctionnait pas sur x86 et comment le réparer. p>
Voici mon code de test: p>
test_exception.c p> test_exception.cpp p> construit avec les commandes suivantes: p > gcc -c test_exception.c -o test_exception_c.o
g++ -c test_exception.cpp -o test_exception_cpp.o
g++ test_exception_c.o test_exception_cpp.o -o test_exception
3 Réponses :
Je comprends que vous ne voudrez peut-être pas lire ceci, mais il est probablement une erreur de continuer à exécuter un programme après toute partie em> qui a tenté d'appeler Si une partie du programme appelé Si vous avez inspecté le code source de la bibliothèque et que vous êtes certain qu'aucune corruption ne résultera, la solution la plus propre serait de modifier la bibliothèque elle-même, de sorte qu'elle lève au lieu de quitter. P>
Si la modification de la bibliothèque n'est pas autorisée, l'autre solution propre et correcte consiste à mettre toutes l'utilisation de la bibliothèque dans un processus distinct que vous pouvez surveiller et redémarrer. P> sortie () code> ou similaire. p>
quitte () code>, vous n'avez aucune garantie sur l'état du programme à ce moment-là. Vous ne savez pas si le tas est dans un état cohérent. Vous ne savez pas si la pile est bonne. Si vous convertissez le
Quitter () code> dans un code> code>, le très em> le moins que vous êtes susceptible de rencontrer des fuites de mémoire chaque fois que cela se produit. Vous ne savez pas si la bibliothèque qui a provoqué cette erreur peut être appelée en toute sécurité. P>
Je suis complètement d'accord avec les conseils. Désolé, je n'étais pas plus clair dans le post original. Mon intention n'était pas de "rappeler la bibliothèque" ou "arrêter le programme de quitter", mais simplement pour laisser tous les destructeurs à être appelés afin que les ressources puissent être libérées correctement etc.
Autant que possible, un programme doit utiliser des ressources de manière à ce qu'il soit suffisant pour que le système d'exploitation puisse les libérer lorsque le programme sort. Il existe des circonstances, telles que l'arrêt du système, lorsque le système d'exploitation tuera votre programme sans préavis. Le programme peut également être tué par un utilisateur. Il peut être tué par un serveur SSH lors de la fin de la session SSH - ce qui peut être causé par quelque chose de simple et incontrôlable que la déconnexion du réseau. Si la journalisation ou la signalisation ou une autre sortie est requise pour indiquer la raison de la sortie, je déclencherais cela à partir d'une fonction exécutée à la sortie. Ensuite, sortez.
Le code ci-dessus fonctionne, mais sur X86 avant que GCC 4.6, -fexceptions ou -Funwind-Tables doivent être ajoutés lors de la construction du code C afin que le déroulement de la pile puisse se produire. Vous pouvez voir le Détails ici . P>
Sauf si votre implémentation C ++ n'est cassée, elle appellera des destructeurs pour les variables globales lorsque Pour les trucs globaux sur le tas, vous pouvez utiliser Destructeurs pour des trucs sur la pile est beaucoup plus difficile. La meilleure solution est probablement de veiller à ce que ces destructeurs n'ont pas besoin d'être appelés - tout ce qui doit être nettoyé avant que la sortie soit évoquée par un global (éventuellement à l'aide de membres statiques de classes) qui le nettoyage dans son destructeur. p> EXIT code> est appelé (GCC n'est pas cassé, au moins toutes les versions que j'ai essayées). Donc, vous n'avez besoin que de nettoyer des trucs qui ne seront pas nettoyés par destructeurs de Var globaux. P>
atexit code> pour enregistrer une fonction de nettoyage qui sera appelée lorsque
quitte code> est appelé - cette fonction de nettoyage peut
Supprimer CODE> Tous les objets de tas à nettoyer. P>
@HAROB: Mais la question concerne l'interaction entre C et C ++ (spécifiquement, jetant une exception dans une fonction appelée à partir de c).
N'a-t-il pas quelque chose possible comme définissant un
at_exit () code> gestionnaire IIRC?
@MikeSeyMour je vois, est-il un moyen de faire ça? Je ne pense pas que vous puissiez créer un lien vers une bibliothèque C ++ à partir d'un programme C utilisant des fonctionnalités spécifiques C ++ telles que la surcharge ou les exceptions de fonction. Supposons que vous deviez déclarer le prototype de fonction en C, à quoi ressemblerait-il? Il faudrait
extern "c" code> dans le programme C ++, qui pourrait empêcher la surcharge ou les exceptions de fonction, je devine bien sûr.
@HAROB: Ceci est un programme C ++ avec une seule fonction écrite en C, pas un programme C. Quant à ce que cela ressemblerait: cela ressemblerait à ce que le code dans la question. Peut-être devriez-vous lire la question avant de commencer davantage.
Dans quelles conditions l'appel de la bibliothèque appelle
Quitter code>?
Il y a deux raisons pour une bibliothèque d'invoquer
sortie () code>. Le premier est le total et la désinvolidité totale du programmeur qui pense qu'il s'agit d'un moyen valide de gérer les erreurs. Je préférerais garder la distance de ces bibliothèques. L'autre cas est une condition fatale que la manipulation normale des erreurs ne peut pas corriger, comme par ex. Le répertoire du plug-in vital n'existe pas ou une erreur de programmation est détectée. Même là, en utilisant
avortement () code> plutôt pour déclencher le débogueur serait le choix préféré. Dans cet esprit, j'aurais une deuxième question de David pourquoi la bibliothèque appelle
sortie () code> du tout.
FWIW Ce code fonctionne pour moi avec GCC 4.8.1 sur Linux; Mais d'autres compilateurs peuvent se comporter différemment lorsque des exceptions se propagent par les fonctions C.
Quitter () CODE> est appelé sous "Conditions d'erreur lorsque le programme devrait fermer" mais ma question n'est pas "est-ce un bon moyen de faire des choses?". Je dois utiliser cette bibliothèque, je ne peux pas le changer et j'essaie de rendre les choses plus agréables avec C ++.
@MikeSeyMour J'avais essayé ceci sur 32 bits Rhel 6 (GCC 4.4.7-11), donc je l'ai essayé sur une machine Rhel 7 de 64 bits (GCC 4.8.3-9) et cela a tout fonctionné. J'ai ensuite essayé sur une machine Rhel 6 64 bits et cela a fonctionné aussi bien. Voici ce juste un bug avec GCC sur des systèmes 32 bits?
Si tout le reste échoue, vous pouvez exécuter la bibliothèque via
Fork code> appels.
@ νταῥεῖ:
at_exit () code> ne vous aide pas vraiment ici. Le programme se termine toujours une fois les fonctions enregistrées. Vous pouvez avoir un
AT_Exit () CODE> -RÉMOINE COMMENT Appeler quelque chose qui continue à faire le travail du programme, mais lorsque
Quitter () code> est appelé à nouveau après cela (terminaison normale de
Main () Code>), le comportement n'est pas défini.
Je n'ai pas d'accès pratique à une machine X86 pour vérifier, mais vous avez déjà fait des choses largement similaires, je vous suggère de regarder
-NOSTDLIB CODE> et
ET
-PRINT-libgcc-file-Name < / code> options. Ce qui se passe, je pense, est que
g ++ code> invoque la lieur avec l'exécution standard devant i> le fichier avec votre redéfinition de
sortie code>, et La commande de recherche de liaison trouve donc la standard
Quitter code> d'abord. Vous voulez que la commande de recherche soit
principale code>, (votre module définissant
Quitter code>) et alors i>
-Lgcc code>. Alors quelque chose comme
g ++ -nostdlib test_exception_c.o test_exception_cpp.o -o test_exception -lgcc code> pourrait le faire.
Après coup: c'est probablement évident, mais vous devez utiliser
g ++ -v code> pour regarder la ligne de liaison que
g ++ code> génère, ce qui peut préciser, par l'ordre des arguments à la liaison, où vient le problème.
@Normangray L'ordre de tout était fondamentalement la même chose avec l'exception mineure que X64 avait des chemins supplémentaires à la lib64. Voici les différences de paramètres: "--with-arc = i686 vs --with-arch_32 = i686", "-March = i686 vs rien" et "-m elf_i386 vs -m el_x86_64".
@Davejohanansen
exit code> pourrait bien être dans
lib64 code> (probablement, mais je ne sais pas). Moi-même, j'essaierais
-nostdlib code> et amis, pour appuyer
lib64 code> à la fin de la liste. Cela régnerait cela, au moins.
@Normangray je sais que ma version de
EXIT code> est appelée parce qu'elle imprime que "Terminez appelé après avoir lancé ..." et cela ne se produirait pas si ma version de
quitte code > n'était pas appelé. En outre, la liaison avec
-NOSTDLIB code> provoque un tas de références non définies afin que je ne crois pas que c'est le problème.
@Davejohanansen ah bien. Entre et ascendant, hein ...
Même si cela a fonctionné, cela aurait l'effet secondaire de la rupture
sortie code> dans des cas légitimes ...