Как надежно заменить библиотечный обработчик ошибок своим собственным? - PullRequest
2 голосов
/ 18 марта 2010

В некоторых случаях ошибки ATL вызывает AtlThrow(), который реализован как ATL::AtlThrowImpl(), который в свою очередь выдает CAtlException. Последнее не очень хорошо - CAtlException даже не является производным от std::exception, и мы также используем нашу собственную иерархию исключений, и теперь нам придется ловить CAtlException отдельно здесь и там, что является большим количеством дополнительного кода и подвержено ошибкам .

Похоже, можно заменить ATL::AtlThrowImpl() на мой собственный обработчик - определите _ATL_CUSTOM_THROW и определите AtlThrow() в качестве пользовательского обработчика перед включением atlbase.h - и ATL вызовет пользовательский обработчик.

Не так просто. Часть кода ATL отсутствует в исходных кодах - она ​​поставляется в виде библиотеки - статической или динамической. Мы используем статический - atls.lib. И ... он скомпилирован таким образом, что внутри него есть ATL::ThrowImpl() и некоторый код, вызывающий его. Я использовал инструмент статического анализа - он ясно показывает, что есть пути, по которым вызывается старый обработчик по умолчанию.

Чтобы убедиться, что я даже попытался "переопределить" ATL::AtlThrowImpl() в своем коде. Теперь компоновщик говорит, что видит два объявления ATL::AtlThrowImpl(), которые, как я полагаю, подтверждают, что есть другая реализация, которая может быть вызвана некоторым кодом.

Как я могу справиться с этим? Как полностью заменить обработчик по умолчанию и гарантировать, что обработчик по умолчанию никогда не вызывается?

Ответы [ 2 ]

1 голос
/ 30 марта 2010

Я давно не работал с этими библиотеками Windows, но вы должны быть в состоянии заставить компоновщик выбрать замену, поместив его в статическую библиотеку, указанную ранее в операторе ссылки. Убедитесь, что вы используете ту же сигнатуру метода, что и оригинал. Вы также можете поиграть с флагами компоновщика, чтобы пропустить библиотеки по умолчанию, для различных определений по умолчанию.

Если у вас есть друг с доступом к MSDN, у него могут быть некоторые источники отладки ATL, что также помогает.

И, как говорит Патрик, вам необходимо обеспечить замену всего, что находится в той же области связи. Некоторые библиотеки разбивают отдельные методы на отдельные объектные файлы, чтобы упростить замену одного элемента. Это чаще встречается, например, c стандартной библиотекой, чем для класса. Если есть много кода ATL, способного вызывать их throw impl в одном объектном файле, это может быть более болезненным, чем оно того стоит…. Возможно, вам придется попробовать перехватить и перебросить как свой собственный тип.

1 голос
/ 23 марта 2010

Я столкнулся с подобными проблемами при написании собственного менеджера памяти и хотел отменить malloc и free.

Проблема в том, что ATL :: AtlThrowImpl, вероятно, является частью исходного файла, который также включает другие файлы, которые действительно необходимы.

Если компоновщик видит ссылку на функцию в одном из объектных файлов, он извлекает объектный файл с этой функцией, включая все другие функции в этом же объектном файле.

Решение состоит в том, чтобы найти источники ATL, в которых определен ATL :: AtlThrowImpl, и посмотреть, содержат ли источник другие функции. Вам также нужно будет реализовать другие функции, чтобы компоновщик не имел ссылки на исходный источник ATL.

...