Mi programa se bloquea al azar en un pequeño escenario que puedo reproducir, pero ocurre en mlock.c (que es un archivo de tiempo de ejecución de VC++) de ntdll.dll, y no puedo ver el rastro de pila Sin embargo, sé que sucede en una de mis funciones de subprocesos.VC++ 2010: error de la sección Weird Critical
Este es el código mlock.c donde el programa se bloquea:
void __cdecl _unlock (
int locknum
)
{
/*
* leave the critical section.
*/
LeaveCriticalSection(_locktable[locknum].lock);
}
el error es "identificador no válido especificado". Si miro a locknum, es un número más grande que el tamaño de la tabla de bloqueo, por lo que tiene sentido.
Esto parece estar relacionado con el uso de Sección crítica. Utilizo CRITICAL_SECTIONS en mi hilo, a través de una clase contenedora CCriticalSection y su guardia RAII asociada, CGuard. Las definiciones para ambos here para evitar aún más desorden.
Ésta es la función del hilo que está chocando:
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;
}
dónde viene CCriticalSection
entrar? Cada objeto CImage
contiene un objeto CCriticalSection
que utiliza a través de un bloqueo RAII CGuard
. Además, cada CImage
contiene un objeto CSharedMemory
que implementa el recuento de referencias. Con ese fin, contiene dos CCriticalSection
también, uno para los datos y otro para el contador de referencia. Un buen ejemplo de estas interacciones se ve mejor en los destructores:
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;
}
¿Alguien se topó con este tipo de error? ¿Cualquier sugerencia?
Editar: Tengo que ver un montón de llamadas: la llamada proviene de ~ CSharedMemory. Así que tiene que haber alguna condición de carrera no
Editar: Código Más CSharedMemory here
¿Daño en la memoria? –
Las dos clases se ven bien. ¿Puedes mostrar algún código relacionado con CÓMO los estás usando? ¿Estás seguro de que los constructores se llaman correctamente antes del uso (no hay conflicto de hilos en los constructores?). ¿Están siendo asignados dinámicamente (por alguna razón)? – Chad
Tu clase no tiene nada que ver con el código CRT, usa Windows. La depuración de las carreras de subprocesos y la corrupción de montón nunca es divertida, buena suerte con ella. –