以下方法在
CHtmlView 会导致内存泄漏如果调用:
- 导航
- GetFullName
- GetType
- GetLocationName
- GetLocationURL
- LoadFromResource(LPCTSTR lpszResource)
- LoadFromResource(UINT nRes)
原因
此问题是由在"摘要"一节中列出的前五个函数内部的实现中的错误引起的。必须在前五个函数中 分配的 bstr 上调用 SysFreeString。因为在这两种这些函...
此问题是由在"摘要"一节中列出的前五个函数内部的实现中的错误引起的。必须在前五个函数中
分配的 bstr 上调用
SysFreeString。因为在这两种这些函数称为
CHtmlView::Navigate 和
CHtmlView::Navigate 导致泄漏,最后两个函数将导致泄漏。
解决方案
要变通解决此泄漏,"摘要"中列出的函数必须在每个从 CHtmlView 派生的类中实现。如果您有多个视图派生 CHtmlView 一些,请考虑从 CHtmlVi...
要变通解决此泄漏,"摘要"中列出的函数必须在每个从
CHtmlView 派生的类中实现。如果您有多个视图派生
CHtmlView 一些,请考虑从 CHtmlView,使新基类,如
CFixHtmlView,然后派生
CFixHtmlView 代替
CHtmlView 视图中的其余部分:
- 在 MFC 应用程序项目中内, 插入一个新的类。在 插入 菜单上单击 新建类别。新建类别 对话框中确保 类类型 设置为 MFC 类。
- 命名类 CFixHtmlView,然后将 基类 组合框项设置为 CHtmlView。
- FixHtmlView.h 文件中将下面的代码添加到类:
class CFixHtmlView : public CHtmlView { //new code // Operations public: CString GetFullName() const; CString GetType() const; CString GetLocationName() const; CString GetLocationURL() const; void Navigate(LPCTSTR lpszURL, DWORD dwFlags = 0 , LPCTSTR lpszTargetFrameName = NULL , LPCTSTR lpszHeaders = NULL, LPVOID lpvPostData = NULL, DWORD dwPostDataLen = 0); //Add the following functions. This action prevents the leak because the //CHtmlView versions of LoadFromResource() call CHtmlView::Navigate(). //These need to be defined because CHtmlView::Navigate() is not virtual. BOOL LoadFromResource(LPCTSTR lpszResource); BOOL LoadFromResource(UINT nRes); //end new code
- FixHtmlView.cpp 文件中添加以下代码:
//new code CString CFixHtmlView::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 CFixHtmlView::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 CFixHtmlView::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 CFixHtmlView::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 CFixHtmlView::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 CFixHtmlView::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 CFixHtmlView::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; } //end new code
- 在每个 CHtmlView-派生类的头和源代码文件更改 CHtmlViewCFixHtmlView 到引用的所有代码。若要帮助完成此任务在 编辑 菜单上单击 替换。
- 确保每个 CHtmlView 中添加下面的代码行的派生类的头文件,在类声明之前:
#include "FixHtmlView.h" //Add me before the class declaration. class CMyHtmlView : public CFixHtmlView { //class body };
- 重新生成项目。