моя программа просачивается с ресурса, принадлежащего boost :: shared_ptr - PullRequest
7 голосов
/ 17 апреля 2011

Я не понимаю, почему у моей программы есть утечка, может быть, вы можете ее обнаружить.

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 ]

2 голосов
/ 17 апреля 2011

В VS2010 std::vector<> была (есть?) Ошибка, приводившая к утечке памяти при определенных обстоятельствах (см. здесь ). AFAIK, это было исправлено в VS2010 SP1, но я не на 100% уверен.

0 голосов
/ 17 апреля 2011

Не собираюсь отвечать на ваш вопрос (как я не вижу проблем), но пара моментов:

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;
}
0 голосов
/ 17 апреля 2011

Я согласился с предложением Джеймса:

@ freefallr: Нет;когда у вас есть std :: map m;и вы делаете m.insert (std :: make_pair (0, std :: string ("Hello World"))) ;, копия временного std :: string ("Hello World") вставляется в std::карта.- Джеймс МакНеллис

...