win7+ie9的一个crash/hung问题的解决

正开发的一个软件遇到了一个奇怪的问题,还Windows 7 + IE9 (x86 & x64) 平台下,会出现一些奇怪的问题,有crash, 有hung, 但也不是每次都出,出现概率不大,一天可能能遇到一次。在网上搜索了一下,发现也有人遇到同样的问题,但是都没有结果。

crash的时候是在mshtml里面,因为我们的应用使用了IWebBrowser来嵌入网页,页面中还有flash,具体出错的位置在

d2d1!CD3DRenderState::BeginDeviceStateChange+0x17

这里访问了一个非法指针,再查,这个指针是d3d10.dll中的一个函数地址。

 

也就是说,d3d10.dll被卸载了,但是d2d1.dll仍然去调用它。

但是d3d10.dll为什么被卸载还是不清楚,最后在一台机器上终于通过断点找到问题。问题的根源出在DirectX10上,d2d1是通过d3d10_1.dll的一个GetD3d10Entry函数来获得d3d10的函数指针,但是GetD3d10Entry函数有问题,它使用以下代码获得函数指针

PFUNC GetD3d10Entry(LPCTSTR pszFunctionName)

{

     HMODULE hMod = GetModuleHandle("d3d10.dll");

    if (!hMod)

    {

        hMod = LoadLibrary("d3d10.dll");

    }

    PFUNC pFunc = GetProcAddress(hMod, pszFunctionName);

    return pFunc;

}

 

问题出在第1行代码上,这个函数首先通过GetModuleHandle来获得dll的句柄,如果得不到,就用LoadLibrary加载,这样可以保证只加载一次d3d10.dll,不会多次LoadLibrary。

但问题是GetModuleHandle不会增加d3d10的引用计数,也就不会锁定d3d10不被卸载。

如果在执行这个函数之前,d3d10没有被加载,那么这个函数会加载d3d10.dll并且永不释放,d3d10.dll总是有效。但是如果调用这个函数的时候,d3d10.dll被其他代码加载了,这个函数就会偷懒不去加载d3d10而直接使用被加载的那一份,那么当加载d3d10的代码最终释放了d3d10的时候,这个函数指针就失效了。

 

在我们的代码中,新的程序为了加快速度,将一部分初始化代码放到了另外一个线程,而那部分代码中有一个函数最终调用了dxdiagn.dll,结果在启动的时候,有时候这个线程先加载了d3d10,然后释放d3d10之后就出现了问题。

 

不过问题的根本还是在DirectX的d3d10_1.dll的GetD3d10Entry这个函数上,这种不严格的获得函数指针的方式可能会影响所有的directx程序。经过咨询微软, 发现微软已经对这个问题提供了一个hotfix KB2488113,不过这个hotfix只能手工下载安装,无法通过windows自动安装升级。

而我们是无法让每一个用户去更新这个hotfix的。work around的办法很简单,在程序启动的时候先LoadLibrary("d3d10.dll"),可以解决这个问题。然后就是等微软将这个hotfix应用到update中了。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值