Internet Explorer выходит из строя при вызове MSXML2::IXMLDOMDocumentPtr -> Release()
Вопрос
Я создаю расширение оболочки на C ++ (ATL 9) с помощью Visual Studio 2008.Расширение оболочки создает глобальный объект MSXML2::IXMLDOMDocumentPtr m_XmlDoc m_XmlDoc в классе module.Этот m_XmlDoc затем используется в расширении всеми классами для чтения xml-документа.
Проблема, с которой я сталкиваюсь, связана с Internet Explorer.Когда расширение оболочки активно, и я открываю / закрываю Internet Explorer, я получаю диалоговое окно отладки, и IE выходит из строя.В сообщении об ошибке говорится "Необработанное исключение при 0x6aac30f1 в iexplore.exe:0xC0000005:Местоположение чтения с нарушением доступа 0x03050970." Когда я нажимаю "прервать" в окне сообщения, это приводит меня к методу "Release" интеллектуального указателя COM, и ошибка, похоже, связана с m_pInterface-> Release ();
Этот вызов был выполнен из деструктора модуля, и также значение m_pInterface не равно NULL.Я думаю, возможно, Internet Explorer использует XML DOM, и вызов Release создает в нем какую-то проблему.
MSXML2::IXMLDOMDocumentPtr m_XmlDoc;
In _AtlModule.Init() method
::CoInitialize(NULL);
m_XmlDoc.CreateInstance(MSXML2::CLSID_DOMDocument40);
Основной код DllMain:
extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
::CoInitialize(NULL);
if (dwReason == DLL_PROCESS_ATTACH)
{
_AtlModule.Init();
CreateImageLists();
::DisableThreadLibraryCalls(hInstance);
}
hInstance;
return _AtlModule.DllMain(dwReason, lpReserved);
}
Решение 3
Проблема была из-за COM-указателя COM, используемого для XmlDomDocument. Я изменил его на обычный указатель, и он отлично работает даже в Vista.
Эта проблема имеет другое поведение в XP и Vista. В XP я получал необработанное исключение, когда закрывал Internet Explorer. В Vista мне не удалось просмотреть виртуальный диск.
Другие советы
использование DisableThreadLibraryCalls не рекомендуется, вы видели это?
Есть по крайней мере две проблемы с вашим опубликованным кодом:
- Вы вызываете CoInitialize в DllMain.
- Вы создаете COM-объект в DllMain.
- Меня не удивит, если вы делаете что-то в CreateImageLists(), чего вы также не должны делать в DllMain.
Кроме того, причина, по которой ваш сбой был "исправлен" отказом от использования интеллектуального указателя, заключается в том, что теперь вы фактически больше не освобождаете объект.Ваш код поврежден, и отказ от публикации ссылки не является допустимым способом что-либо исправить.
Я бы посоветовал вам прочитать, а затем перечитывать документацию по ДллМейн уделяя особое внимание вещам, которые вы никогда не должны делать в рамках вашей реализации функции.Как вы увидите прямо сейчас:
Предупреждение Существуют серьезные ограничения на то, что вы можете делать в точке входа DLL.Чтобы обеспечить более сложную инициализацию, создайте процедуру инициализации для библиотеки DLL.Вы можете потребовать, чтобы приложения вызывали процедуру инициализации перед вызовом любых других подпрограмм в библиотеке DLL.
Я подозреваю, что как только вы прочтете это и исправите свой код, чтобы создать COM-объект в допустимое время, и выпустите его в допустимое время, ваше расширение оболочки перестанет сбоить.