I can't see why my program is leaking, maybe you can spot it.
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;
}
My class contains this WindowMap population works correctly, but teardown doesn't seem to be working correctly. The class destructor calls this function to clear the map - which should release the shared_ptr's, thereby deleting them, right? :)
void EraseList()
{
m_Windows.clear();
}
I'd love to know what I'm missing - all the StringPtr's are leaking.
UPDATE RE the comment that the "StringPtr(new std::string(sWindowText)))" was stylistically wrong, I made the suggested change, as below, but, the memory leak is still there.
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;
}
Conclusion I've gone with the suggestion of ditching StringPtr and using make_pair(hWnd, std::string()) and have sidestepped the issue that way.
There was (is?) a bug in VS2010 std::vector<>
implementation causing memory to leak under certain circumstances (see here). AFAIK, it has been fixed in VS2010 SP1, but I'm not 100% positive.
Not going to answer your question (as I can;t see any problems) but a couple of points:
typedef std::map < HWND, std::string > WindowMap;
typedef WindowMap::value_type WMapPair; // In the future it may not be a pair.
// Or you may change the type of WindowMap
// Make it so the value is based on the container.
// Done automatically.
// 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
// Declare variables at there first usage point.
// There is no need to clutter the top of the function
// With usless variables that may never be used.
if( ! ::IsWindow( hWnd ) )
return FALSE;
int nTextLen = GetWindowTextLength( hWnd );
if( ! nTextLen )
return TRUE;
// Use a vector. Dynamically allocating memory is dangerious and not
// exception safe (unless you use a smart pointer (or in this case a container))
std::vector<char> sWindowText(nTextLen + 1);
GetWindowTextA( hWnd, &sWindowText[0], nTextLen );
// No need for shared pointers. Just put the string in the map.
m_Windows.insert( WMapPair(hWnd, std::string(sWindowText.begin(),
sWindowText.begin()+ nTextLen)));
return TRUE;
}
I've gone with James' suggestion:
@freefallr: No; when you have a std::map m; and you do a m.insert(std::make_pair(0, std::string("Hello World")));, a copy of the temporary std::string("Hello World") is inserted into the std::map. – James McNellis
精彩评论