2. Что такое valgrind? Valgrind – это набор инструментов, для валидации и профилирования. Valgrind доступен только для Linux и некоторых UNIX (например, для Mac OS X).
10. Memcheck Предназначен для обнаружения ошибок работы с кучей в C и С++ Может обнаружить обращения к высвобожденной области памяти, обращения за пределы выделенной области памяти или memory leak.
11. Как работает Memcheck? При выделении нового куска памяти: Области, которые выделяет valgrind для отслеживания выхода за границу То, что мы выделяем
12. Как работает Memcheck? При высвобождении куска памяти: То, что мы выделили, и хотим высвободить Становится недоступным, но не высвобождается.
13. Как работает Memcheck? Он также контролирует доступ к неинициализированным переменным на стеке, или в статической памяти int main() { int x; printf ("x = %d", x); } Conditional jump or move depends on uninitialised value(s) at 0x402DFA94: _IO_vfprintf (_itoa.h:49) by 0x402E8476: _IO_printf (printf.c:36) by 0x8048472: main (tests/test.cpp:10)
14. Проблемы Memcheck Из-за ограниченности ресурсов нельзя долго держать большие куски памяти Нельзя выделять большие куски памяти для отслеживания выхода за границы Нет механизма отслеживания ошибок работы со стеком или статической памятью
15. Ptrcheck Предназначен для обнаружения ошибок работы с кучей, стеком и статической памятью в C и С++ Это экспериментальный инструмент, который должен определять часть ошибок, которые не определяет Memcheck
19. DRD – отсутствие синхронизации $ valgrind --tool=drd --read-var-info=yes drd/tests/rwlock_race ... ==9466== Thread 3: ==9466== Conflicting load by thread 3 at 0x006020b8 size 4 ==9466== at 0x400B6C: thread_func (rwlock_race.c:29) ==9466== by 0x4C291DF: vg_thread_wrapper (drd_pthread_intercepts.c:186) ==9466== by 0x4E3403F: start_thread (in /lib64/libpthread-2.8.so) ==9466== by 0x53250CC: clone (in /lib64/libc-2.8.so) ==9466== Location 0x6020b8 is 0 bytes inside local var "s_racy" ==9466== declared at rwlock_race.c:18, in frame #0 of thread 3 ==9466== Other segment start (thread 2) ==9466== at 0x4C2847D: pthread_rwlock_rdlock* (drd_pthread_intercepts.c:813) ==9466== by 0x400B6B: thread_func (rwlock_race.c:28) ==9466== by 0x4C291DF: vg_thread_wrapper (drd_pthread_intercepts.c:186) ==9466== by 0x4E3403F: start_thread (in /lib64/libpthread-2.8.so) ==9466== by 0x53250CC: clone (in /lib64/libc-2.8.so) ==9466== Other segment end (thread 2) ==9466== at 0x4C28B54: pthread_rwlock_unlock* (drd_pthread_intercepts.c:912) ==9466== by 0x400B84: thread_func (rwlock_race.c:30) ==9466== by 0x4C291DF: vg_thread_wrapper (drd_pthread_intercepts.c:186) ==9466== by 0x4E3403F: start_thread (in /lib64/libpthread-2.8.so) ==9466== by 0x53250CC: clone (in /lib64/libc-2.8.so)
20. DRD – длительная блокировка Программа hold_lock блокирует mutex на заданное количество милисекунд: ... hold_lock.c:51 pthread_mutex_lock( &mutex ); hold_lock.c:52 hold_lock.c:53 usleep( interval * 1000 ); hold_lock.c:54 hold_lock.c:55 pthread_mutex_unlock( &mutex ); ... $ valgrind --tool=drd --exclusive-threshold=10 drd/tests/hold_lock -i 500 ... ==10668== Acquired at: ==10668== at 0x4C267C8: pthread_mutex_lock (drd_pthread_intercepts.c:395) ==10668== by 0x400D92: main (hold_lock.c:51) ==10668== Lock on mutex 0x7fefffd50 was held during 503 ms (threshold: 10 ms). ==10668== at 0x4C26ADA: pthread_mutex_unlock (drd_pthread_intercepts.c:441) ==10668== by 0x400DB5: main (hold_lock.c:55) ... $ valgrind --tool=drd --exclusive-threshold=10 drd/tests/hold_lock -i 500 ... ==10668== Acquired at: ==10668== at 0x4C267C8: pthread_mutex_lock (drd_pthread_intercepts.c:395) ==10668== by 0x400D92: main (hold_lock.c:51) ==10668== Lock on mutex 0x7fefffd50 was held during 503 ms (threshold: 10 ms). ==10668== at 0x4C26ADA: pthread_mutex_unlock (drd_pthread_intercepts.c:441) ==10668== by 0x400DB5: main (hold_lock.c:55) ...
24. Helgrind – отсутствие синхронизации simple_race.c:3 int var = 0; simple_race.c:4 simple_race.c:5 void* child_fn ( void* arg ) { simple_race.c:6 var++; /* Unprotected relative to parent */ simple_race.c:7 return NULL; simple_race.c:8 } simple_race.c:9 simple_race.c:10 int main ( void ) { simple_race.c:11 pthread_t child; simple_race.c:12 pthread_create(&child, NULL, child_fn, NULL); simple_race.c:13 var++; /* Unprotected relative to child */ simple_race.c:14 pthread_join(child, NULL); simple_race.c:15 return 0; simple_race.c:16 } Possible data race during read of size 4 at 0x601038 by thread #1 at 0x400606: main (simple_race.c:13) This conflicts with a previous write of size 4 by thread #2 at 0x4005DC: child_fn (simple_race.c:6) by 0x4C29AFF: mythread_wrapper (hg_intercepts.c:194) by 0x4E3403F: start_thread (in /lib64/libpthread-2.8.so) by 0x511C0CC: clone (in /lib64/libc-2.8.so) Location 0x601038 is 0 bytes inside global var "var" declared at simple_race.c:3
25. Helgrind – deadlocks Helgrind также сообщает ''правильный'' порядок захвата, но только для случая с двумя объектами синхронизации. Helgrind отслеживает порядок захвата объектов синхронизации. Если два или более объектов синхронизации могут быть захвачены в пределах одного потока в разном порядке – Hellgrind сообщает о проблеме.
26. Helgrind – deadlocks Сообщение о нарушении порядка захвата объектов синхронизации для двух mutex'ов выглядит следующим образом: Thread #1: lock order "0x7FEFFFAB0 before 0x7FEFFFA80" violated at 0x4C23C91: pthread_mutex_lock (hg_intercepts.c:388) by 0x40081F: main (tc13_laog1.c:24) Required order was established by acquisition of lock at 0x7FEFFFAB0 at 0x4C23C91: pthread_mutex_lock (hg_intercepts.c:388) by 0x400748: main (tc13_laog1.c:17) followed by a later acquisition of lock at 0x7FEFFFA80 at 0x4C23C91: pthread_mutex_lock (hg_intercepts.c:388) by 0x400773: main (tc13_laog1.c:18)
27. Как всем этим пользоваться? Valgrind позволяет анализировать только код на ассемблере, C, C++ и FORTRAN. Для начала анализа надо запустить Valgrind с параметром --tool=<инструмент> Например: $> valgrind --tool=hellgrind ./my_app my_param