2010-06-28 13 views
14

Tengo un poco de código con una condición de carrera ... Sé que es una condición de carrera porque no ocurre de manera constante, y parece ocurrir más a menudo en máquinas de doble núcleo .Formas de encontrar una condición de carrera

Nunca sucede cuando estoy rastreando. Aunque existe la posibilidad de que también sea un punto muerto. Al analizar las etapas de finalización de los registros donde esto ocurre y no ocurre, he podido localizar este error en una sola función. Sin embargo, no sé en qué parte de la función esto está sucediendo. No está en el nivel superior.

Agregar declaraciones de registro o puntos de interrupción va a cambiar el tiempo si se trata de una condición de carrera, y evitar que esto suceda.

¿Existe alguna técnica que pueda usarse aparte de la obtención de un analizador de condiciones de carrera que me permita identificar dónde ocurre esto?

Esto está en el estudio visual 9, con C++ (de la variedad no administrada).

+0

última vez que tuve una condición de carrera en serio, sabía local donde se estaba produciendo . Lo hice a la "manera antigua" y recurrí a gráficos de árboles de llamadas y resaltar las duraciones de bloqueo para cada llamada a mano. En mi caso, fue relegado a 2 archivos fuente y un puñado de funciones, pero resultó invaluable. –

Respuesta

4

Colóquelo en varias partes de su código. Algo que es seguro para la realización de hilos será seguro incluso si (o el código asíncrono) duerme por unos segundos.

2

De hecho, hay algunos intentos de encontrar condiciones de carrera automáticamente.

Otro término que he leído en conjunción con la detección de condición de carrera es RaceFuzzer, pero no fue capaz de encontrar información realmente útil al respecto.

Creo que este es un campo de investigación relativamente joven por lo que hay, por lo que sé, principalmente trabajos teóricos sobre este tema. Sin embargo, intente buscar en Google una de las palabras clave anteriores, tal vez encontrará algo de información útil.

3

La mejor forma que conozco para realizar un seguimiento de estos es utilizar CHESS en Visual Studio. Esta no es una herramienta simple de usar, y probablemente requerirá probar subsecciones de su aplicación progresivamente. Buena suerte.

0

Podría intentar publicar el código. Intel también ofrece varias herramientas paralelas que puedes probar.

2

He tenido un poco de suerte al usar los puntos de seguimiento de Visual Studio para encontrar condiciones de carrera. Por supuesto, todavía afecta el tiempo, pero en los casos en que lo usé, al menos, no fue suficiente para evitar por completo las condiciones de carrera. Parecía menos perjudicial que el registro dedicado, al menos.

Aparte de eso, intente publicar el código para que otros puedan verlo. Solo estudiar el código en detalle no es una mala forma de encontrar las condiciones de carrera.

+0

+1 Para revisiones de código. Las revisiones de código siempre son una buena cosa. –

1

También puede ser un recurso que no está protegido, lo que puede explicar el comportamiento no consistente (especialmente si en un solo núcleo funciona bien y no en doble núcleo). En cualquier caso, la revisión del código (tanto para las condiciones de carrera como para el código fuente no seguro para subprocesos) puede ser el camino más corto hacia la solución.

2

Por lo tanto, el método de mazo para mí ha sido el siguiente, que requiere mucha paciencia y, en el mejor de los casos, puede llevarlo por el camino correcto.Usé esto para descubrir qué estaba pasando con este problema en particular. He estado usando puntos de rastreo, uno al comienzo de la función sospechosa de alto nivel y uno al final. Mueve el punto de seguimiento hacia abajo. Si agregar el punto de rastreo al principio de la función hace que su error deje de suceder, mueva el punto de rastreo hacia abajo hasta que pueda reproducir la condición nuevamente. La idea es que el punto de seguimiento no afectará el tiempo si lo coloca después de la llamada que finalmente desencadena un código inseguro, pero lo hará si lo coloca antes. Además, tenga en cuenta su ventana de salida. ¿Entre qué mensajes está ocurriendo tu error? Puede usar puntos de referencia para restringir este rango también.

Una vez que reduce su error a una región de código manejable, puede agregar puntos de interrupción y ver qué están haciendo los otros hilos en este momento.

1

Puede usar herramientas como Intel Inspector que pueden verificar ciertos tipos de condiciones de carrera.

5

Hay una herramienta incluida en CLang y gcc 4.8+ llamada ThreadSanitizer.

compilar el código usando la bandera -fsanitize=thread

Ejemplo:

$ cat simple_race.cc 
#include <pthread.h> 
#include <stdio.h> 

int Global; 

void *Thread1(void *x) { 
    Global++; 
    return NULL; 
} 

void *Thread2(void *x) { 
    Global--; 
    return NULL; 
} 

int main() { 
    pthread_t t[2]; 
    pthread_create(&t[0], NULL, Thread1, NULL); 
    pthread_create(&t[1], NULL, Thread2, NULL); 
    pthread_join(t[0], NULL); 
    pthread_join(t[1], NULL); 
} 

Y la salida

$ clang++ simple_race.cc -fsanitize=thread -fPIE -pie -g 
$ ./a.out 
================== 
WARNING: ThreadSanitizer: data race (pid=26327) 
    Write of size 4 at 0x7f89554701d0 by thread T1: 
    #0 Thread1(void*) simple_race.cc:8 (exe+0x000000006e66) 

    Previous write of size 4 at 0x7f89554701d0 by thread T2: 
    #0 Thread2(void*) simple_race.cc:13 (exe+0x000000006ed6) 

    Thread T1 (tid=26328, running) created at: 
    #0 pthread_create tsan_interceptors.cc:683 (exe+0x00000001108b) 
    #1 main simple_race.cc:19 (exe+0x000000006f39) 

    Thread T2 (tid=26329, running) created at: 
    #0 pthread_create tsan_interceptors.cc:683 (exe+0x00000001108b) 
    #1 main simple_race.cc:20 (exe+0x000000006f63) 
================== 
ThreadSanitizer: reported 1 warnings 
Cuestiones relacionadas