注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

mie

 
 
 

日志

 
 

VC 2010 sp1+MFC:CMapStringToPtr::SetAt()函数导致的内存泄露  

2011-07-08 15:09:51|  分类: Windows系统BUG搜 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

此为VC 2010 的MFC库的又一内存泄露。

 

内存分配时的堆栈如下:

   MaskScreen.exe!_heap_alloc_dbg_impl(unsigned int nSize=164, int nBlockUse=1, const char * szFileName=0x00b75300, int nLine=29, int * errno_tmp=0x0012d96c)  行 393 C++
  MaskScreen.exe!_nh_malloc_dbg_impl(unsigned int nSize=164, int nhFlag=0, int nBlockUse=1, const char * szFileName=0x00b75300, int nLine=29, int * errno_tmp=0x0012d96c)  行 239 + 0x19 字节 C++
  MaskScreen.exe!_nh_malloc_dbg(unsigned int nSize=164, int nhFlag=0, int nBlockUse=1, const char * szFileName=0x00b75300, int nLine=29)  行 302 + 0x1d 字节 C++
  MaskScreen.exe!_malloc_dbg(unsigned int nSize=164, int nBlockUse=1, const char * szFileName=0x00b75300, int nLine=29)  行 160 + 0x1b 字节 C++
  MaskScreen.exe!operator new(unsigned int nSize=164, int nType=1, const char * lpszFileName=0x00b75300, int nLine=29)  行 379 + 0x15 字节 C++
  MaskScreen.exe!operator new[](unsigned int nSize=164, int nType=1, const char * lpszFileName=0x00b75300, int nLine=29)  行 411 + 0x15 字节 C++
  MaskScreen.exe!operator new[](unsigned int nSize=164, const char * lpszFileName=0x00b75300, int nLine=29)  行 62 + 0x13 字节 C++
  MaskScreen.exe!CPlex::Create(CPlex * & pHead=0x00000000, unsigned int nMax=10, unsigned int cbElement=16)  行 29 + 0x17 字节 C++
  MaskScreen.exe!CMapStringToPtr::NewAssoc()  行 136 + 0x15 字节 C++
  MaskScreen.exe!CMapStringToPtr::operator[](const wchar_t * key=0x0142d480)  行 239 + 0x8 字节 C++
  MaskScreen.exe!CMapStringToPtr::SetAt(const wchar_t * key=0x0142d480, void * newValue=0x00000000)  行 628 + 0x15 字节 C++
  MaskScreen.exe!CToolTipCtrl::OnAddTool(unsigned int wParam=0, long lParam=1236488)  行 92 C++
  MaskScreen.exe!CWnd::OnWndMsg(unsigned int message=1074, unsigned int wParam=0, long lParam=1236488, long * pResult=0x0012dc48)  行 2383 + 0x11 字节 C++
  MaskScreen.exe!CWnd::WindowProc(unsigned int message=1074, unsigned int wParam=0, long lParam=1236488)  行 2087 + 0x20 字节 C++
  MaskScreen.exe!AfxCallWndProc(CWnd * pWnd=0x0142d360, HWND__ * hWnd=0x00100cca, unsigned int nMsg=1074, unsigned int wParam=0, long lParam=1236488)  行 257 + 0x1c 字节 C++
  MaskScreen.exe!AfxWndProc(HWND__ * hWnd=0x00100cca, unsigned int nMsg=1074, unsigned int wParam=0, long lParam=1236488)  行 420 C++
  user32.dll!_InternalCallWinProc@20()  + 0x28 字节 
  user32.dll!_UserCallWinProcCheckWow@32()  + 0xa2 字节 
  user32.dll!_SendMessageWorker@20()  + 0xdb 字节 
  user32.dll!_SendMessageW@16()  + 0x49 字节 
  MaskScreen.exe!CToolTipCtrl::AddTool(CWnd * pWnd=0x0142c370, const wchar_t * lpszText=0x0142d480, const tagRECT * lpRectTool=0x00000000, unsigned int nIDTool=0)  行 154 C++
> MaskScreen.exe!CMFCButton::SetTooltip(const wchar_t * lpszToolTipText=0x0142d480)  行 1006 C++
  MaskScreen.exe!CMFCButton::OnInitControl(unsigned int wParam=369, long lParam=12915136)  行 1542 C++
  MaskScreen.exe!CWnd::OnWndMsg(unsigned int message=892, unsigned int wParam=369, long lParam=12915136, long * pResult=0x0012e080)  行 2383 + 0x11 字节 C++

 

            导致内存泄露的根源在于,CToolTipCtrl::OnAddTool时(D:\Program Files\Microsoft Visual Studio 10.0\VC\atlmfc\src\mfc\tooltip.cpp的89行),
  void* pv;
  if (!m_mapString.Lookup(ti.lpszText, pv))
   m_mapString.SetAt(ti.lpszText, NULL);

          代码中,在Lookup查表时,没有找到表项,于是,调用SetAt来分配一个表项。

 

而SetAt的代码如下:

d:\Program Files\Microsoft Visual Studio 10.0\VC\atlmfc\include\afxcoll.inl(627行)

_AFXCOLL_INLINE void CMapStringToPtr::SetAt(LPCTSTR key, void* newValue)
 { (*this)[key] = newValue; }

 

这里使用了[]运算符,而[]运算符已经被重载,代码如下:

D:\Program Files\Microsoft Visual Studio 10.0\VC\atlmfc\src\mfc\map_sp.cpp(262行)


void*& CMapStringToPtr::operator[](LPCTSTR key)
{
 ASSERT_VALID(this);

 UINT nHashBucket, nHashValue;
 CAssoc* pAssoc;
 if ((pAssoc = GetAssocAt(key, nHashBucket, nHashValue)) == NULL)
 {
  if (m_pHashTable == NULL)
   InitHashTable(m_nHashTableSize);

  // it doesn't exist, add a new Association
  pAssoc = NewAssoc();                   //内存分配
  pAssoc->nHashValue = nHashValue;
  pAssoc->key = key;
  // 'pAssoc->value' is a constructed object, nothing more

  // put into hash table
  pAssoc->pNext = m_pHashTable[nHashBucket];
  m_pHashTable[nHashBucket] = pAssoc;
 }
 return pAssoc->value;  // return new reference
}

其中,NewAssoc再调用new分配内存,在程序退出时,MFC运行时库并没有对此进行检测和回收,从而导致内存泄露。

 

内存泄露时的Trace信息:

Detected memory leaks!
Dumping objects ->
f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\plex.cpp(29) : {459} normal block at 0x0142CD70, 164 bytes long.
 Data: <                > 00 00 00 00 00 00 00 00 C5 9D 1C 81 80 AB C2 00
f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\map_sp.cpp(83) : {458} normal block at 0x0142CB50, 68 bytes long.
 Data: <    t B         > 00 00 00 00 74 CD 42 01 00 00 00 00 00 00 00 00
f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\afxtooltipmanager.cpp(70) : {457} client block at 0x0142CCA0, subtype c0, 144 bytes long.
a CToolTipCtrl object at $0142CCA0, 144 bytes long

 

vc7libs?,,,,

 

调用CMapStringToPtr::RemoveAll等函数,都不能消除内存泄露。

 

By:zhanyonhu

  评论这张
 
阅读(1856)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2016