I'm running into a perplexing problem with an ActiveX control I'm writing - sometimes, Internet Explorer appears to fail to properly unload the control on process shutdown. This results in the control instance's destructor not being called.
我正在使用我正在编写的ActiveX控件遇到一个令人困惑的问题 - 有时,Internet Explorer似乎无法在进程关闭时正确卸载控件。这导致控件实例的析构函数未被调用。
The control is written in C++, uses ATL and it's compiled using Visual Studio 2005. The control instance's destructor is always called when the user browses away from the page the control is embedded in - the problem only occurs when the browser is closed.
控件是用C ++编写的,使用ATL并使用Visual Studio 2005进行编译。当用户浏览控件所嵌入的页面时,总是调用控件实例的析构函数 - 问题只发生在浏览器关闭时。
When I run IE under a debugger, I don't see anything unusual - the debugger doesn't catch any exceptions, access violations or assertion failures, but the problem is still there - I can set a breakpoint in the control's destructor and it's never hit when I close the broswer.
当我在调试器下运行IE时,我没有看到任何异常 - 调试器没有捕获任何异常,访问冲突或断言失败,但问题仍然存在 - 我可以在控件的析构函数中设置断点,它永远不会当我关闭broswer时打。
In addition, when I load a simple HTML page that embeds multiple instances of the control I don't see the problem. The problem only appears to happen when the control is instantiated from our web application, which inserts tags dynamically into the web page - of course, not knowing what causes this problem, I don't know whether this bit of information is relevant or not, but it does seem to indicate that this might be an IE problem, since it's data dependent.
另外,当我加载一个嵌入控件的多个实例的简单HTML页面时,我没有看到问题。只有从我们的Web应用程序实例化控件时才会出现问题,该应用程序将标签动态插入到网页中 - 当然,不知道导致此问题的原因,我不知道这些信息是否相关,但它似乎表明这可能是一个IE问题,因为它依赖于数据。
When I run the simple test case under the debugger, I can set a breakpoint in the control's destructor and it's hit every time. I believe this rules out a problem with the control itself (say, an error that would prevent the destructor from ever being called, like an interface leak.)
当我在调试器下运行简单的测试用例时,我可以在控件的析构函数中设置一个断点,并且每次都会命中它。我相信这排除了控件本身的问题(比如,一个错误会阻止析构函数被调用,就像接口泄漏一样。)
I do most of my testing with IE 6, but I've seen the problem occur on IE 7, as well. I haven't tested IE 8.
我使用IE 6进行了大部分测试,但我也看到了IE 7上出现的问题。我还没有测试IE 8。
My working hypothesis right now is that there's something in the dynamic HTML code that causes the browser to leak an interface on the ActiveX control. So far, I haven't been able to produce a good test case that reproduces this outside of the application, and the application is a bit too large to make a good test case.
我现在的工作假设是,动态HTML代码中存在导致浏览器泄漏ActiveX控件上的接口的内容。到目前为止,我还没有能够生成一个很好的测试用例,可以在应用程序之外再现这个,并且应用程序有点太大而无法构建一个好的测试用例。
I was hoping that someone might be able to provide insight into possible IE bugs that are known to cause this kind of behavior. The answer provided below, by the way, is too general - I'm looking for a specific set of circumstances that is known to cause this. Surely someone out there has seen this before.
我希望有人能够深入了解可能导致此类行为的IE错误。顺便提一下,下面提供的答案太笼统了 - 我正在寻找一组特定的情况,这些情况已知会引起这种情况。当然有人在那里见过这个。
3 个解决方案
#1
3
To debug a problem in COM with C++ where an object's (C++) destructor is not being called, the best approach is to focus on how the COM object's refcounts are being incremented or decremented. What is probably happening is that somebody is incrementing the refcount one too many times, and then not decrementing it the same number of times. This leads to the object not being freed.
要使用C ++调试COM中的问题,其中没有调用对象的(C ++)析构函数,最好的方法是关注COM对象的refcounts如何递增或递减。可能发生的事情是有人将refcount增加了太多次,然后没有减少相同的次数。这导致对象不被释放。
It is possible that your dynamic HTML is simply showing up a bug in IE, which doesn't happen if you use a static page.
您的动态HTML可能只是在IE中显示错误,如果您使用静态页面则不会发生这种错误。
If there is a bug in IE, the trick would be to figure out what causes the bug to appear, and what you can do to trick IE into releasing your COM object properly (like, making the HTML go away).
如果IE中存在错误,那么诀窍就是找出导致错误出现的原因,以及你可以做些什么来诱骗IE正确发布你的COM对象(比如,让HTML消失)。
#2
0
Another approach - add cleanup code to your DllMain function (adding that function if it doesn't already exist). Then regardless of reference counts (and reference count errors), when your DLL is unloaded you can clean yourself up:
另一种方法 - 将清理代码添加到DllMain函数中(如果该函数尚不存在则添加该函数)。然后,无论引用计数(和引用计数错误)如何,当您的DLL被卸载时,您可以清理自己:
BOOL WINAPI DllMain(HINSTANCE, DWORD dwReason, LPVOID) {
if (dwReason == DLL_PROCESS_DETACH) {
CleanUpAnyObjectsStillAlive();
}
}
Oh, and a word of warning - don't take too long doing your cleanup - if you do, I can't promise the process shutdown won't kill you anyway.
哦,还有一句警告 - 不要花太多时间进行清理 - 如果你这样做,我不能保证过程关闭不会杀死你。
#3
0
I have the same problem, but only on a specific computer. This computer also has a problem with the Flash ActiveX, that remains alive after closing the tab. My guess is that the problem is not with your code. Do you have that problem on other computers?
我有同样的问题,但只在特定的计算机上。此计算机还存在Flash ActiveX问题,在关闭选项卡后仍然存在。我的猜测是问题不在你的代码上。你在其他电脑上有这个问题吗?
#1
3
To debug a problem in COM with C++ where an object's (C++) destructor is not being called, the best approach is to focus on how the COM object's refcounts are being incremented or decremented. What is probably happening is that somebody is incrementing the refcount one too many times, and then not decrementing it the same number of times. This leads to the object not being freed.
要使用C ++调试COM中的问题,其中没有调用对象的(C ++)析构函数,最好的方法是关注COM对象的refcounts如何递增或递减。可能发生的事情是有人将refcount增加了太多次,然后没有减少相同的次数。这导致对象不被释放。
It is possible that your dynamic HTML is simply showing up a bug in IE, which doesn't happen if you use a static page.
您的动态HTML可能只是在IE中显示错误,如果您使用静态页面则不会发生这种错误。
If there is a bug in IE, the trick would be to figure out what causes the bug to appear, and what you can do to trick IE into releasing your COM object properly (like, making the HTML go away).
如果IE中存在错误,那么诀窍就是找出导致错误出现的原因,以及你可以做些什么来诱骗IE正确发布你的COM对象(比如,让HTML消失)。
#2
0
Another approach - add cleanup code to your DllMain function (adding that function if it doesn't already exist). Then regardless of reference counts (and reference count errors), when your DLL is unloaded you can clean yourself up:
另一种方法 - 将清理代码添加到DllMain函数中(如果该函数尚不存在则添加该函数)。然后,无论引用计数(和引用计数错误)如何,当您的DLL被卸载时,您可以清理自己:
BOOL WINAPI DllMain(HINSTANCE, DWORD dwReason, LPVOID) {
if (dwReason == DLL_PROCESS_DETACH) {
CleanUpAnyObjectsStillAlive();
}
}
Oh, and a word of warning - don't take too long doing your cleanup - if you do, I can't promise the process shutdown won't kill you anyway.
哦,还有一句警告 - 不要花太多时间进行清理 - 如果你这样做,我不能保证过程关闭不会杀死你。
#3
0
I have the same problem, but only on a specific computer. This computer also has a problem with the Flash ActiveX, that remains alive after closing the tab. My guess is that the problem is not with your code. Do you have that problem on other computers?
我有同样的问题,但只在特定的计算机上。此计算机还存在Flash ActiveX问题,在关闭选项卡后仍然存在。我的猜测是问题不在你的代码上。你在其他电脑上有这个问题吗?