Il mio programma si blocca in modo casuale in un piccolo scenario che posso riprodurre, ma succede in mlock.c (che è un file di runtime VC++) da ntdll.dll, e non riesco a vedere il traccia dello stack. So che succede in una delle mie funzioni thread, però.VC++ 2010: errore di sezione critica strano
Questo è il codice mlock.c in cui il programma si blocca:
void __cdecl _unlock (
int locknum
)
{
/*
* leave the critical section.
*/
LeaveCriticalSection(_locktable[locknum].lock);
}
L'errore è "handle non valido specificato". Se guardo il locknum, è un numero più grande della dimensione di _locktable, quindi questo ha un senso.
Questo sembra essere correlato all'utilizzo della sezione critica. Uso CRITICAL_SECTIONS nella mia discussione, tramite una classe wrapper CCriticalSection e la relativa protezione RAII associata, CGuard. Definizioni per entrambi here per evitare ancora più confusione.
Questa è la funzione di filo che è schiantarsi:
unsigned int __stdcall CPlayBack::timerThread(void * pParams) {
#ifdef _DEBUG
DRA::CommonCpp::SetThreadName(-1, "CPlayBack::timerThread");
#endif
CPlayBack * pThis = static_cast<CPlayBack*>(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<DWORD>(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;
}
dove viene CCriticalSection
entrare? Ogni oggetto CImage
contiene un oggetto CCriticalSection
che utilizza tramite un blocco RAII CGuard
. Inoltre, ogni CImage
contiene un oggetto CSharedMemory
che implementa il conteggio dei riferimenti. A tal fine, contiene anche due CCriticalSection
, uno per i dati e uno per il contatore di riferimento. Un buon esempio di queste interazioni è visto meglio nelle distruttori:
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;
}
Chiunque urtato questo tipo di errore? Qualche suggerimento?
Modifica: Ho visto alcuni stack di chiamate: la chiamata proviene da ~ CSharedMemory. Quindi ci deve essere una certa condizione di competizione ci
Edit: codice più CSharedMemory here
Corruzione della memoria? –
Le due classi stesse stanno bene. Puoi mostrare qualche codice relativo a COME li stai usando? Sei sicuro che i costruttori siano chiamati correttamente prima dell'uso (nessuna contesa sul thread sui costruttori?). Sono assegnati dinamicamente (per qualche motivo)? – Chad
La tua classe non ha nulla a che fare con il codice CRT, usa Windows. Il debugging delle gare di threading e della corruzione dell'heap non è mai divertente, buona fortuna. –