我的程序泄漏了boost :: shared_ptr所拥有的资源

时间:2011-04-16 23:45:18

标签: c++ boost memory-leaks stdmap

我看不出为什么我的程序漏了,也许你可以发现它。

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都在泄漏。

更新 的 RE注释“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())的建议,并以这种方式回避了这个问题。

3 个答案:

答案 0 :(得分:2)

VS2010 std::vector<>实施中存在(是?)错误,导致内存在某些情况下泄露(请参阅here)。 AFAIK,它已在VS2010 SP1中修复,但我不是100%正面。

答案 1 :(得分:0)

我和詹姆斯的建议一致:

@freefallr:不;当你有一个std :: map m;并且你做一个m.insert(std :: make_pair(0,std :: string(“Hello World”)));,将临时std :: string(“Hello World”)的副本插入到std中: :地图。 - 詹姆斯麦克尼利斯

答案 2 :(得分:0)

不会回答你的问题(我可以看到任何问题),但有几点:

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;
}