• 使用mfc CHtmlView内存泄露解决方法


    第一步,谷歌有文章说CHtmlView部分api使用BSTR没释放:

    解决方法是重写一下接口:

    CString GetFullName() const;
    CString GetFullName() const;
    CString GetType() const;
    CString GetLocationName() const;
    CString GetLocationURL() const;
    void Navigate(LPCTSTR URL, DWORD dwFlags = 0,
    LPCTSTR lpszTargetFrameName = NULL,
    LPCTSTR lpszHeaders = NULL, LPVOID lpvPostData = NULL,
    DWORD dwPostDataLen = 0);
    BOOL LoadFromResource(LPCTSTR lpszResource);
    BOOL LoadFromResource(UINT nRes);
    CString CHtmlViewEx::GetFullName() const
    {
        ASSERT(m_pBrowserApp != NULL);
    
        BSTR bstr;
        m_pBrowserApp->get_FullName(&bstr);
        CString retVal(bstr);
    
        SysFreeString(bstr); // Added this line to prevent leak.
        return retVal;
    }
    
    CString CHtmlViewEx::GetType() const
    {
        ASSERT(m_pBrowserApp != NULL);
    
        BSTR bstr;
        m_pBrowserApp->get_Type(&bstr);
    
        CString retVal(bstr);
    
        SysFreeString(bstr); // Added this line to prevent leak.
        return retVal;
    }
    
    CString CHtmlViewEx::GetLocationName() const
    {
        ASSERT(m_pBrowserApp != NULL);
    
        BSTR bstr;
        m_pBrowserApp->get_LocationName(&bstr);
        CString retVal(bstr);
    
        SysFreeString(bstr); // Added this line to prevent leak.
        return retVal;
    }
    
    CString CHtmlViewEx::GetLocationURL() const
    {
        ASSERT(m_pBrowserApp != NULL);
    
        BSTR bstr;
        m_pBrowserApp->get_LocationURL(&bstr);
        CString retVal(bstr);
    
        SysFreeString(bstr); // Added this line to prevent leak.
        return retVal;
    }
    
    void CHtmlViewEx::Navigate(LPCTSTR lpszURL, DWORD dwFlags /*= 0*/, LPCTSTR lpszTargetFrameName /*= NULL*/, LPCTSTR lpszHeaders /*= NULL*/, LPVOID lpvPostData /*= NULL*/, DWORD dwPostDataLen /*= 0*/)
    {
        CString strURL(lpszURL);
        BSTR bstrURL = strURL.AllocSysString();
    
        COleSafeArray vPostData;
        if (lpvPostData != NULL)
        {
            if (dwPostDataLen == 0)
                dwPostDataLen = lstrlen((LPCTSTR)lpvPostData);
    
            vPostData.CreateOneDim(VT_UI1, dwPostDataLen, lpvPostData);
        }
    
        m_pBrowserApp->Navigate(bstrURL, COleVariant((long)dwFlags, VT_I4), COleVariant(lpszTargetFrameName, VT_BSTR),
            vPostData, COleVariant(lpszHeaders, VT_BSTR));
    
        SysFreeString(bstrURL); // Added this line to prevent leak.
    }
    
    BOOL CHtmlViewEx::LoadFromResource(LPCTSTR lpszResource)
    {
        HINSTANCE hInstance = AfxGetResourceHandle();
        ASSERT(hInstance != NULL);
    
        CString strResourceURL;
        BOOL bRetVal = TRUE;
        LPTSTR lpszModule = new TCHAR[_MAX_PATH];
    
        if (GetModuleFileName(hInstance, lpszModule, _MAX_PATH))
        {
            strResourceURL.Format(_T("res://%s/%s"), lpszModule, lpszResource);
            Navigate(strResourceURL, 0, 0, 0);
        }
        else
            bRetVal = FALSE;
    
        delete[] lpszModule;
        return bRetVal;
    }
    
    BOOL CHtmlViewEx::LoadFromResource(UINT nRes)
    {
        HINSTANCE hInstance = AfxGetResourceHandle();
        ASSERT(hInstance != NULL);
    
        CString strResourceURL;
        BOOL bRetVal = TRUE;
        LPTSTR lpszModule = new TCHAR[_MAX_PATH];
    
        if (GetModuleFileName(hInstance, lpszModule, _MAX_PATH))
        {
            strResourceURL.Format(_T("res://%s/%d"), lpszModule, nRes);
            Navigate(strResourceURL, 0, 0, 0);
        }
        else
            bRetVal = FALSE;
    
        delete[] lpszModule;
        return bRetVal;
    }

    第二步,由于加载页面js脚本并没有释放js变量所分配的内存,有两种解决方法:第一种,调用本地html文件,调用CollectGarbage()接口回收变量的内存,html文件代码如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head> 
    
    <body>
        <script type="text/javascript">
            if (typeof window.CollectGarbage === 'function') {
                CollectGarbage()
            }
        </script>
    
    </body>
    </html> 

    第二种:如果不需要调用html页面的js代码,可以直接关闭IE浏览器的js脚本功能:https://jingyan.baidu.com/article/48206aead44e53216ad6b397.html 

    转载请注明出处,from博客园hemjohn

  • 相关阅读:
    浅谈Spring AOP 面向切面编程 最通俗易懂的画图理解AOP、AOP通知执行顺序~
    fastjson自由:controller上指定active profile,让你想序列化什么字段就序列化什么字段
    Java多线程中join、yield、sleep方法详解
    一张图秒懂微服务网络架构
    详解SpringBoot应用跨域访问解决方案
    如何在 Spring/Spring Boot 中做参数校验?你需要了解的都在这里!
    史上最全的excel读写技术分享
    手把手教你定制标准Spring Boot starter,真的很清晰
    JVM性能调优详解
    Spring Boot 2.x监控数据可视化(Actuator + Prometheus + Grafana手把手)
  • 原文地址:https://www.cnblogs.com/HemJohn/p/10901681.html
Copyright © 2020-2023  润新知