【发布时间】:2011-04-16 23:45:17
【问题描述】:
我不明白为什么我的程序会泄漏,也许你能发现它。
typedef boost::shared_ptr < std::string > StringPtr;
typedef std::pair < HWND, StringPtr > WMapPair;
typedef std::map < HWND, StringPtr > WindowMap;
// this callback populates the WindowMap (m_Windows) by adding a WMapPair each time
BOOL CALLBACK EnumWindowsCallback( HWND hWnd )
{
// adds this window to the WindowMap, along with its title text
BOOL bRetVal = FALSE;
int nTextLen = 0;
char* sWindowText = NULL;
if( ! ::IsWindow( hWnd ) )
return FALSE;
nTextLen = GetWindowTextLength( hWnd );
if( ! nTextLen )
return TRUE;
sWindowText = new char[nTextLen + 1];
if( sWindowText )
{
GetWindowTextA( hWnd, sWindowText, nTextLen );
m_Windows.insert( WMapPair(hWnd, StringPtr(new std::string(sWindowText))) );
delete [] sWindowText;
sWindowText = NULL;
bRetVal = TRUE;
}
return bRetVal;
}
我的类包含这个 WindowMap 人口可以正常工作,但拆解似乎不能正常工作。类析构函数调用此函数来清除映射 - 这应该释放 shared_ptr,从而删除它们,对吗? :)
void EraseList()
{
m_Windows.clear();
}
我很想知道我缺少什么 - 所有的 StringPtr 都在泄漏。
更新 重新评论“StringPtr(new std::string(sWindowText)))”在风格上是错误的,我做了如下建议的更改,但是内存泄漏仍然存在。
BOOL CALLBACK EnumWindowsCallback( HWND hWnd )
{
// adds this window to the WindowMap, along with its title text
BOOL bRetVal = FALSE;
int nTextLen = 0;
char* sWindowText = NULL;
StringPtr strPtr;
if( ! ::IsWindow( hWnd ) )
return FALSE;
nTextLen = GetWindowTextLength( hWnd );
if( ! nTextLen )
return TRUE;
sWindowText = new char[nTextLen + 1];
if( sWindowText )
{
GetWindowTextA( hWnd, sWindowText, nTextLen );
strPtr = StringPtr(new std::string(sWindowText));
m_Windows.insert( WMapPair(hWnd, strPtr) );
delete [] sWindowText;
sWindowText = NULL;
bRetVal = TRUE;
}
return bRetVal;
}
结论 我已经接受了放弃 StringPtr 并使用 make_pair(hWnd, std::string()) 的建议,并以这种方式回避了这个问题。
【问题讨论】:
-
这在风格上是错误的:
StringPtr(new std::string(sWindowText))。每个新的动态分配对象最初都应该由一个 named 智能指针拥有。更多信息,请阅读the Boostshared_ptrbest practices。另外,考虑使用std::vector<char>而不是自己动态分配数组。不过,我认为这些都不是导致您的具体问题的原因。 -
@freefallr:不;当您有一个
std::map<int, std::string> m;并且您执行一个m.insert(std::make_pair(0, std::string("Hello World")));时,临时std::string("Hello World")的副本将插入到std::map。 -
你确定你没有循环引用吗?这就是 boost::weak_ptr 的用途。
-
您需要将向量调整为足够大,然后您可以使用
&v[0]获取指向其初始元素的指针。例如:std::vector<TCHAR> v(nTextLen + 1); GetWindowText(hWnd, &v[0], nTextLen); -
@freefallr - 不,它不能! :-) 您链接到的页面是针对
operator new的,这是一个您可以覆盖的运算符,以便为某个类型分配一些特殊的内存。我的页面是关于new的声明,例如new x。尽管他们都使用new这个词,但它们的含义不同。我可以向你保证new x不会返回 NULL,它会抛出异常。
标签: c++ boost memory-leaks stdmap