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

my program is leaking with resource owned by boost::shared_ptr

本文关键字:ptr 拥有 资源 shared 泄漏 boost 我的 程序      更新时间:2023-10-16

我不知道为什么我的程序会泄漏,也许你能发现它。

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人口工作正常,但teardown似乎不能正常工作。类析构函数调用这个函数来清除映射——这应该释放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()),并以这种方式回避了这个问题。

在VS2010 std::vector<>实现中存在(is?)一个bug,导致在某些情况下内存泄漏(参见这里)。我敢说,它已经在VS2010 SP1中修复了,但我不是100%肯定。

不打算回答你的问题(因为我看不到任何问题),但有几点:

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

我接受了James的建议:

@freefallr:没有;当你有std::map m;然后执行m.s insert(std::make_pair(0, std::string("Hello World")));,临时std::string("Hello World")的副本被插入到std::map中。- James McNellis