CHtmlView在做网页浏览媒介的时候,你会发现,当前程序存在内存泄漏问题,在经过百度和google之后,找到了这个在MSDN里的问题和答案。

原文链接:http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q241750#top

原文主要内容:

发现内存泄漏的是这几个方法:

The following methods in CHtmlView cause a memory leak if called:

  1. Navigate 
  2. GetFullName 
  3. GetType 
  4. GetLocationName 
  5. GetLocationURL 
  6. LoadFromResource(LPCTSTR lpszResource) 
  7. LoadFromResource(UINT nRes) 

原因:

This problem is caused by bugs in the internal implementation in the first five functions listed in the "Summary" section. SysFreeString must be called in the first five functions on the allocated BSTRs. The last two functions cause a leak because CHtmlView::Navigate is called in both of these functions and CHtmlView::Navigate causes a leak.

 

解决办法:

这里提到的解决办法就是重载这几个方法,在返回前,释放BSTR的内存数据。

如下源码:

.H文件的源码:

  1. class CFixHtmlView : public CHtmlView 
  2. //new code 
  3. // Operations 
  4. public
  5.     CString GetFullName() const
  6.     CString GetType() const
  7.     CString GetLocationName() const
  8.     CString GetLocationURL() const
  9.  
  10.     void Navigate(LPCTSTR lpszURL, DWORD dwFlags = 0 ,   
  11.                   LPCTSTR lpszTargetFrameName = NULL ,   
  12.                   LPCTSTR lpszHeaders = NULL, LPVOID lpvPostData = NULL,   
  13.                   DWORD dwPostDataLen = 0); 
  14.  
  15. //Add the following functions. This action prevents the leak because the  
  16. //CHtmlView versions of LoadFromResource() call CHtmlView::Navigate(). 
  17. //These need to be defined because CHtmlView::Navigate() is not virtual. 
  18.     BOOL LoadFromResource(LPCTSTR lpszResource); 
  19.     BOOL LoadFromResource(UINT nRes); 
  20. //end new code 

.CPP文件的代码:

  1. //new code 
  2. CString CFixHtmlView::GetFullName() const 
  3.     ASSERT(m_pBrowserApp != NULL); 
  4.  
  5.     BSTR bstr; 
  6.     m_pBrowserApp->get_FullName(&bstr); 
  7.     CString retVal(bstr); 
  8.  
  9.     SysFreeString(bstr); // Added this line to prevent leak. 
  10.     return retVal; 
  11.  
  12. CString CFixHtmlView::GetType() const 
  13.     ASSERT(m_pBrowserApp != NULL); 
  14.  
  15.     BSTR bstr; 
  16.     m_pBrowserApp->get_Type(&bstr); 
  17.  
  18.     CString retVal(bstr); 
  19.  
  20.     SysFreeString(bstr); // Added this line to prevent leak. 
  21.     return retVal; 
  22.  
  23. CString CFixHtmlView::GetLocationName() const 
  24.     ASSERT(m_pBrowserApp != NULL); 
  25.  
  26.     BSTR bstr; 
  27.     m_pBrowserApp->get_LocationName(&bstr); 
  28.     CString retVal(bstr); 
  29.  
  30.     SysFreeString(bstr); // Added this line to prevent leak. 
  31.     return retVal; 
  32.   
  33. CString CFixHtmlView::GetLocationURL() const 
  34.     ASSERT(m_pBrowserApp != NULL); 
  35.  
  36.     BSTR bstr; 
  37.     m_pBrowserApp->get_LocationURL(&bstr); 
  38.     CString retVal(bstr); 
  39.  
  40.     SysFreeString(bstr); // Added this line to prevent leak. 
  41.     return retVal; 
  42.  
  43. void CFixHtmlView::Navigate(LPCTSTR lpszURL, DWORD dwFlags /* = 0 */
  44.     LPCTSTR lpszTargetFrameName /* = NULL */ , 
  45.     LPCTSTR lpszHeaders /* = NULL */LPVOID lpvPostData /* = NULL */
  46.     DWORD dwPostDataLen /* = 0 */
  47.     CString strURL(lpszURL); 
  48.     BSTR bstrURL = strURL.AllocSysString(); 
  49.  
  50.     COleSafeArray vPostData; 
  51.     if (lpvPostData != NULL) 
  52.     { 
  53.        if (dwPostDataLen == 0) 
  54.           dwPostDataLen = lstrlen((LPCTSTR) lpvPostData); 
  55.  
  56.        vPostData.CreateOneDim(VT_UI1, dwPostDataLen, lpvPostData); 
  57.     } 
  58.  
  59.     m_pBrowserApp->Navigate(bstrURL, COleVariant((long) dwFlags, VT_I4), 
  60. COleVariant(lpszTargetFrameName, VT_BSTR),  
  61.                             vPostData, COleVariant(lpszHeaders, VT_BSTR)); 
  62.  
  63.     SysFreeString(bstrURL); // Added this line to prevent leak. 
  64.  
  65.  
  66. BOOL CFixHtmlView::LoadFromResource(LPCTSTR lpszResource) 
  67.     HINSTANCE hInstance = AfxGetResourceHandle(); 
  68.     ASSERT(hInstance != NULL); 
  69.  
  70.     CString strResourceURL; 
  71.     BOOL bRetVal = TRUE; 
  72.     LPTSTR lpszModule = new TCHAR[_MAX_PATH]; 
  73.  
  74.     if (GetModuleFileName(hInstance, lpszModule, _MAX_PATH)) 
  75.     { 
  76.        strResourceURL.Format(_T("res://%s/%s"), lpszModule, lpszResource); 
  77.        Navigate(strResourceURL, 0, 0, 0); 
  78.     } 
  79.     else 
  80.        bRetVal = FALSE; 
  81.  
  82.     delete [] lpszModule; 
  83.     return bRetVal; 
  84.  
  85. BOOL CFixHtmlView::LoadFromResource(UINT nRes) 
  86.     HINSTANCE hInstance = AfxGetResourceHandle(); 
  87.     ASSERT(hInstance != NULL); 
  88.  
  89.     CString strResourceURL; 
  90.     BOOL bRetVal = TRUE; 
  91.     LPTSTR lpszModule = new TCHAR[_MAX_PATH]; 
  92.  
  93.     if (GetModuleFileName(hInstance, lpszModule, _MAX_PATH)) 
  94.     { 
  95.        strResourceURL.Format(_T("res://%s/%d"), lpszModule, nRes); 
  96.        Navigate(strResourceURL, 0, 0, 0); 
  97.     } 
  98.     else 
  99.        bRetVal = FALSE; 
  100.  
  101.     delete [] lpszModule; 
  102.     return bRetVal; 
  103. //end new code 

 

之后就是让目标类继承于当前的CFixHtmlView类,而不继承于CHtmlView类。

如下代码:

  1. #include "FixHtmlView.h" //Add me before the class declaration. 
  2.  
  3. class CMyHtmlView : public CFixHtmlView 
  4. //class body 
  5. };