2010-03-18 4 views
2

Sur certains cas d'erreur ATL invoque AtlThrow() qui est implémenté en tant que ATL::AtlThrowImpl() qui à son tour lance CAtlException. Ce dernier n'est pas très bon - CAtlException n'est même pas dérivé de std::exception et aussi nous utilisons notre propre hiérarchie d'exceptions et maintenant nous devrons attraper CAtlException séparément ici et là ce qui est beaucoup de code supplémentaire et sujet aux erreurs.Comment remplacer de manière fiable un gestionnaire d'erreurs défini par la bibliothèque avec le mien?

On dirait qu'il est possible de remplacer ATL::AtlThrowImpl() avec mon propre gestionnaire - définir _ATL_CUSTOM_THROW et définir AtlThrow() être le gestionnaire personnalisé avant d'inclure atlbase.h - et ATL appellera le gestionnaire personnalisé.

Pas si facile. Une partie du code ATL n'est pas dans les sources - il est compilé en tant que bibliothèque - statique ou dynamique. Nous utilisons le statique - atls.lib. Et ... il est compilé de telle sorte qu'il a ATL::ThrowImpl() à l'intérieur et du code l'appelant. J'ai utilisé un outil d'analyse statique - il montre clairement qu'il y a des chemins sur lesquels l'ancien gestionnaire par défaut est appelé.

Pour s'assurer que j'ai même essayé de "réimplémenter" ATL::AtlThrowImpl() dans mon code. Maintenant, l'éditeur de liens dit qu'il voit deux déclarations de ATL::AtlThrowImpl() qui, je suppose, confirme qu'il existe une autre implémentation qui peut être appelée par du code.

Comment puis-je gérer cela? Comment puis-je remplacer complètement le gestionnaire par défaut et m'assurer que le gestionnaire par défaut n'est jamais appelé?

Répondre

1

J'ai rencontré des problèmes similaires lors de l'écriture de mon propre gestionnaire de mémoire et je voulais annuler malloc et libre.

Le problème est que ATL :: AtlThrowImpl fait probablement partie d'un fichier source qui inclut également d'autres fichiers réellement nécessaires. Si l'éditeur de liens voit une référence à une fonction dans l'un des fichiers objet, il extrait le fichier objet avec cette fonction, y compris toutes les autres fonctions dans ce même fichier objet.

La solution est de rechercher dans les sources ATL où ATL :: AtlThrowImpl est défini et voir si la source contient d'autres fonctions. Vous devrez également implémenter les autres fonctions pour empêcher l'éditeur de liens d'avoir une référence à la source ATL d'origine.

+1

Vous avez raison, mais il s'avère que le problème est AtlThrowImpl() est une fonction inline et ceux qui sont gérés spécialement - http://blogs.msdn.com/b/aszego/archive/2010/05/12/override -atlthrow-with-care.aspx donc la ligne du bas est en cours La conception ATL nécessite une recompilation de la librairie pour remplacer le gestionnaire. – sharptooth

+0

Il est évidemment impossible de contourner les méthodes en ligne de cette manière. Je ne vois aucune solution pour cela, sauf pour modifier les en-têtes et recompiler toute la bibliothèque ATL. – Patrick

1

Je n'ai pas travaillé ces bibliothèques Windows depuis longtemps, mais vous devriez être en mesure d'obtenir l'éditeur de liens pour choisir votre remplacement en le plaçant dans une bibliothèque statique répertoriée plus haut dans l'instruction link. Assurez-vous que vous utilisez la même signature de méthode que l'original. Vous pouvez également jouer avec les indicateurs de liens pour omettre les bibliothèques par défaut, pour différentes définitions de défaut.

Si vous avez un ami avec accès à MSDN, il peut avoir certaines sources de débogage ATL, ce qui aide également. Et, comme le dit Patrick, vous devez remplacer tous les éléments de la même portée de liaison. Certaines bibliothèques décomposent les méthodes individuelles en fichiers objets distincts pour faciliter le remplacement d'une pièce. C'est plus commun avec, par exemple, c standard lib que pour une classe. S'il y a beaucoup de code ATL capable d'appeler leur impl implier dans un seul fichier objet, cela peut être plus douloureux que cela en vaut la peine ... vous devrez peut-être essayer de le réécrire comme votre propre type.