VC ++ 2010: Weird Critical Section error

Моя программа случайно дает сбой в небольшом сценарии, который я могу воспроизвести, но это происходит в mlock.c (который является файлом времени выполнения VC ++) из ntdll.dll, и я не могу увидеть трассировку стека. Однако я знаю, что это происходит в одной из моих потоковых функций.

Это код mlock.c, в котором происходит сбой программы:

void __cdecl _unlock (
        int locknum
        )
{
        /*
         * leave the critical section.
         */
        LeaveCriticalSection( _locktable[locknum].lock );
}

Ошибка: «Указан неверный дескриптор». Если я посмотрю на locknum, это число больше, чем размер _locktable, так что в этом есть некоторый смысл.

Похоже, это связано с использованием Critical Section. Я использую CRITICAL_SECTIONS в своем потоке через класс-оболочку CCriticalSection и связанный с ним защиту RAII, CGuard. Определения для обоих здесь , чтобы избежать еще большего беспорядка.

Это функция потока, которая дает сбой:

unsigned int __stdcall CPlayBack::timerThread( void * pParams ) {
#ifdef _DEBUG
    DRA::CommonCpp::SetThreadName( -1, "CPlayBack::timerThread" );
#endif
    CPlayBack * pThis = static_cast( pParams );
    bool bContinue = true;
    while( bContinue ) {
        float m_fActualFrameRate = pThis->m_fFrameRate * pThis->m_fFrameRateMultiplier;
        if( m_fActualFrameRate != 0 && pThis->m_bIsPlaying ) {
            bContinue = ( ::WaitForSingleObject( pThis->m_hEndThreadEvent, static_cast( 1000.0f / m_fActualFrameRate ) ) == WAIT_TIMEOUT );
            CImage img;
            if( pThis->m_bIsPlaying && pThis->nextFrame( img ) )
                pThis->sendImage( img );
        }
        else
            bContinue = ( ::WaitForSingleObject( pThis->m_hEndThreadEvent, 10 ) == WAIT_TIMEOUT );
    }
    ::GetErrorLoggerInstance()->Log( LOG_TYPE_NOTE, "CPlayBack", "timerThread", "Exiting thread" );
    return 0;
}

Откуда тут CCriticalSection ? Каждый объект CImage содержит объект CCriticalSection , который он использует посредством блокировки CGuard RAII. Более того, каждый CImage содержит объект CSharedMemory , который реализует подсчет ссылок. С этой целью он также содержит два CCriticalSection , один для данных и один для счетчика ссылок. Хороший пример такого взаимодействия лучше всего можно увидеть в деструкторах:

CImage::~CImage() {
    CGuard guard(m_csData);
    if( m_pSharedMemory != NULL ) {
        m_pSharedMemory->decrementUse();
        if( !m_pSharedMemory->isBeingUsed() ){
            delete m_pSharedMemory;
            m_pSharedMemory = NULL;
        }
    }
    m_cProperties.ClearMin();
    m_cProperties.ClearMax();
    m_cProperties.ClearMode();
}

CSharedMemory::~CSharedMemory() {
    CGuard guardUse( m_cs );
    if( m_pData && m_bCanDelete ){
        delete []m_pData;
    }
    m_use = 0;
    m_pData = NULL;
}

Кто-нибудь сталкивался с такого рода ошибкой? Есть предложения?

Edit : Мне нужно увидеть стек вызовов: вызов поступает из ~ CSharedMemory. Так что там должно быть какое-то состояние гонки

Правка : Подробнее код CSharedMemory здесь

5
задан dario_ramos 19 August 2011 в 19:35
поделиться