2010-03-18 1 views
2

В некоторых случаях ошибки 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(), которые, я полагаю, подтверждают, что есть другая реализация, которую может вызывать какой-то код.

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

ответ

1

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

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

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

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

+1

Вы правы, но проблема заключается в том, что AtlThrowImpl() является встроенной функцией, и те обрабатываются специально - http://blogs.msdn.com/b/aszego/archive/2010/05/12/override -atlthrow-with-care.aspx, поэтому нижняя строка - это текущий дизайн ATL, требует перекомпиляции библиотеки для замены обработчика. – sharptooth

+0

Переопределение встроенных методов таким образом, конечно, невозможно. Я не вижу решения для этого, кроме как изменить заголовки и перекомпилировать всю библиотеку ATL. – Patrick

1

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

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

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

Смежные вопросы