Cuando comencé a aprender la herramienta valgrind (helgrind), me encontré con un problema tan difícil que no pude abordar.por qué valgrind (helgrind) genera "Razas de datos posibles" en caso de que se invoque una función virtual en mi estructura de hilos
En simple, se crea una clase de subproceso definida por el usuario con una función virtual a la que se llamaría mediante la rutina de entrada del subproceso. Si este es el caso, helgrind informará Posible-data-race. Pero después de simplemente omitir la palabra clave virtual, no se informará ningún error. ¿Cómo es que esto sucede de esta manera? ¿Hay algún problema con mi código? ¿O hay una solución alternativa?
De ahora en adelante es la sencilla aplicación de subprocesos que demuestra tal problema, incluyendo cpp, Makefile y mensajes que ayudan a generar informes.
/* main.cpp */
#include <memory.h>
#include <pthread.h>
class thread_s {
public:
pthread_t th;
thread_s(void);
~thread_s(void);
virtual void* routine(); /* if omit virtual, no error would be generated */
void stop(void);
};
static void* routine(void*);
int main(int, const char*[])
{
thread_s s_v;
pthread_create(&s_v.th, 0, routine, &s_v);
return 0;
}
static void* routine(void* arg)
{
thread_s *pV = reinterpret_cast<thread_s*>(arg);
pV->routine();
return 0;
}
void* thread_s::routine(void)
{
return 0;
}
thread_s::thread_s(void)
{
th = 0;
}
thread_s::~thread_s(void)
{
stop();
}
void thread_s::stop(void)
{
void *v = 0;
pthread_join(th, &v);
}
=======================================
/* Makefile */
all: main test_helgrind
main: main.cpp
g++ -o main main.cpp \
-g -Wall -O0 \
-lpthread
test_helgrind:
valgrind \
--tool=helgrind \
./main
clean:
rm -f main
.PHONY: clean
=======================================
g++ -o main main.cpp \
-g -Wall -O0 \
-lpthread
valgrind \
--tool=helgrind \
./main
==7477== Helgrind, a thread error detector
==7477== Copyright (C) 2007-2010, and GNU GPL'd, by OpenWorks LLP et al.
==7477== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
==7477== Command: ./main
==7477==
==7477== Thread #1 is the program's root thread
==7477==
==7477== Thread #2 was created
==7477== at 0x4259728: clone (clone.S:111)
==7477== by 0x40484B5: [email protected]@GLIBC_2.1 (createthread.c:256)
==7477== by 0x4026E2D: pthread_create_WRK (hg_intercepts.c:257)
==7477== by 0x4026F8B: [email protected]* (hg_intercepts.c:288)
==7477== by 0x8048560: main (main.cpp:18)
==7477==
==7477== Possible data race during write of size 4 at 0xbeab24c8 by thread #1
==7477== at 0x80485C9: thread_s::~thread_s() (main.cpp:35)
==7477== by 0x8048571: main (main.cpp:17)
==7477== This conflicts with a previous read of size 4 by thread #2
==7477== at 0x804858B: routine(void*) (main.cpp:24)
==7477== by 0x4026F60: mythread_wrapper (hg_intercepts.c:221)
==7477== by 0x4047E98: start_thread (pthread_create.c:304)
==7477== by 0x425973D: clone (clone.S:130)
==7477==
==7477==
==7477== For counts of detected and suppressed errors, rerun with: -v
==7477== Use --history-level=approx or =none to gain increased speed, at
==7477== the cost of reduced accuracy of conflicting-access information
==7477== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 1 from 1)
Bueno, el acceso a 's_v' no parece estar sincronizado ... –