Development/Valgrind: Difference between revisions
No edit summary |
S Richling (talk | contribs) m (S Richling moved page Valgrind to Development/Valgrind: Umzung in Developmentbereich) |
||
(8 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
{{Softwarepage|devel/valgrind}} |
|||
<!--{| align="right" {{Table|width=40%}} --> |
|||
{|{{Softwarebox}} |
|||
{| width=600px class="wikitable" |
|||
|- |
|- |
||
! Description !! Content |
|||
! colspan="2" style="text-align:center" | Valgrind |
|||
⚫ | |||
| module load devel/valgrind |
|||
⚫ | |||
| Availability |
|||
| [[bwUniCluster]] | [[BwForCluster_Chemistry]] |
|||
|- |
|- |
||
| License |
| License |
||
| [http://www.gnu.org/licenses/ GPL] |
|||
| GPL |
|||
|- |
|- |
||
|Citing |
|Citing |
||
| |
| n/a |
||
|- |
|- |
||
| Links |
| Links |
||
| [http://valgrind.org/ Homepage] |
| [http://valgrind.org/ Valgrind Homepage] |
||
⚫ | |||
|- |
|- |
||
| Graphical Interface |
| Graphical Interface |
||
| No |
| No |
||
|- |
|||
|} |
|} |
||
<br> |
|||
⚫ | |||
= Introduction = |
|||
'''Valgrind''' is an instrumentation framework for building dynamic analysis tools. The main (default) tool <kbd>memcheck</kbd> detects a wide variety of memory management bugs. This page introduces the various tools to fetch threading bugs, and profile your programs in detail. As such, any programmer '''must''' know valgrind's memcheck. |
|||
While the Linux distribution provides valgrind, this module comes with a newer version (which may interpret newer instruction sets) and more tools than the system provided one. |
|||
<br> |
|||
= Overview = |
|||
{| {{Table}} |
|||
⚫ | |||
{| width=600px class="wikitable" |
|||
|- |
|- |
||
! Tool |
! Tool |
||
Line 25: | Line 37: | ||
|- |
|- |
||
| memcheck |
| memcheck |
||
| Detects heap array |
| Detects heap array over- and underruns, usage of uninitialized memory, memory leaks and incorrect freeing of heap memory. |
||
⚫ | |||
| exp-sgcheck |
|||
| Detects stack and global array overruns. |
|||
|- |
|- |
||
| callgrind |
| callgrind |
||
| Memory Profiler. Together with kcachegrind allows getting an overview of applications and getting details about memory access and costs. |
|||
| Profiler. Helps finding bottlenecks. |
|||
|- |
|- |
||
| helgrind |
| helgrind |
||
Line 38: | Line 47: | ||
| drd |
| drd |
||
| Detects race conditions. Does not detect deadlocks but needs less memory than helgrind. |
| Detects race conditions. Does not detect deadlocks but needs less memory than helgrind. |
||
|- |
|||
| massif |
|||
| A heap memory profiler showing the allocation history over time. |
|||
|} |
|} |
||
<br> |
|||
= Documentation = |
|||
'''Loading:''' There is no need for loading valgrind because it is available by default. |
|||
== Online == |
|||
[http://valgrind.org/docs/ Online Valgrind Documentation] |
|||
== Local == |
|||
'''Online documentation:''' http://valgrind.org/docs/ |
|||
<pre>$ man valgrind</pre> |
|||
<br> |
|||
= Usage = |
|||
To simulate your program and gather information about it using a specific tool, valgrind can be called like this |
To simulate your program and gather information about it using a specific tool, valgrind can be called like this |
||
<pre>$ valgrind --tool=<tool> --log-file=<logfile> ./example</pre> |
<pre>$ valgrind --tool=<tool> --log-file=<logfile> ./example</pre> |
||
For example to check for race conditions the command would look like this: |
For example to check for race conditions the command would look like this: |
||
<pre>$ valgrind --tool=drd --log-file=log.mem ./example</pre> |
<pre>$ valgrind --tool=drd --log-file=log.mem ./example</pre> |
||
Line 53: | Line 70: | ||
Beware that the simulation via valgrind can take much longer and can consume much more memory compared to a normal execution. |
Beware that the simulation via valgrind can take much longer and can consume much more memory compared to a normal execution. |
||
Furthermore the tools can give false positives, i.e. they report errors even though the are none. |
Furthermore the tools can give false positives, i.e. they report errors even though the are none. |
||
<br> |
|||
= Example using drd on OpenMP = |
|||
The following simple OpenMP-parallel example shows a data race on global data: |
|||
<source lang=c> |
|||
This small program demonstrates how to detect data races in parallel programs. Both helgrind and drd support POSIX Threads (Pthreads) but not OpenMP so prepare to get many false positives when using these tools with OpenMP. |
|||
#include <stdlib.h> |
|||
#include <stdio.h> |
|||
#include "omp.h" |
|||
int global = 4711; |
|||
int main (int argc, char * argv[]) { |
|||
// The following is an ERROR: This should be a (thread-)local variable. |
|||
#pragma omp parallel |
|||
global = omp_get_thread_num(); |
|||
printf("global:%d\n", global); |
|||
return EXIT_SUCCESS; |
|||
} |
|||
</source> |
|||
Compile this example using |
|||
<pre>$ gcc -Wall -O2 -fopenmp omp_error.c -o omp_error</pre> |
|||
One may optionally pass the <kbd>-g</kbd> to allow Valgrind to print source code lines in the erroneous functions. |
|||
Running this example shows: |
|||
<pre>$ valgrind --tool=drd ./omp_error |
|||
... |
|||
==1019408== Thread 2: |
|||
==1019408== Conflicting store by thread 2 at 0x00601034 size 4 |
|||
==1019408== at 0x4006D9: main._omp_fn.0 (openmp_error_access.c:13) |
|||
... |
|||
==1019408== Allocation context: Data section of /pfs/data5/home/es/es_es/es_rakeller/C/openmp_error_access |
|||
==1019408== Other segment start (thread 1) |
|||
==1019408== at 0x4C3F3CF: pthread_create_intercept (drd_pthread_intercepts.c:625) |
|||
==1019408== by 0x4C3F3CF: pthread_create@* (drd_pthread_intercepts.c:631) |
|||
==1019408== by 0x4E84A72: ??? (in /usr/lib64/libgomp.so.1.0.0) |
|||
==1019408== by 0x4E7A6A0: GOMP_parallel (in /usr/lib64/libgomp.so.1.0.0) |
|||
==1019408== by 0x4005C3: main (openmp_error_access.c:9) |
|||
==1019408== Other segment end (thread 1) |
|||
==1019408== at 0x4E86FAA: ??? (in /usr/lib64/libgomp.so.1.0.0) |
|||
==1019408== by 0x4E85A1C: ??? (in /usr/lib64/libgomp.so.1.0.0) |
|||
==1019408== by 0x4005C3: main (openmp_error_access.c:9) |
|||
==1019408== |
|||
==1019408== Thread 1: |
|||
==1019408== Conflicting load by thread 1 at 0x00601034 size 4 |
|||
==1019408== at 0x4005C4: main (openmp_error_access.c:15) |
|||
==1019408== Allocation context: Data section of /pfs/data5/home/es/es_es/es_rakeller/C/openmp_error_access |
|||
==1019408== Other segment start (thread 2) |
|||
... |
|||
</pre> |
|||
= Example for helgrind for PThreads = |
|||
The following PThread-parallel example demonstrates how to detect data races in parallel programs. |
|||
<source lang=c> |
<source lang=c> |
||
Line 101: | Line 170: | ||
} |
} |
||
</source> |
</source> |
||
Compile the program using |
|||
<pre>$ gcc -Wall pthreads.c -o pthreads -pthread -lm |
<pre>$ gcc -Wall -O2 pthreads.c -o pthreads -pthread -lm</pre> |
||
where -pthread tells the compiler to link against the Pthreads library and -lm is needed for linking against the math library. |
where -pthread tells the compiler to link against the Pthreads library and -lm is needed for linking against the math library. |
||
This program has a race condition, consecutive executions can give different outputs. Such errors are hard to find because they can show up very rarely. |
This program has a race condition, consecutive executions can give different outputs. Such errors are hard to find because they can show up very rarely. |
||
Line 150: | Line 219: | ||
</pre> |
</pre> |
||
The execution can take longer but now we know that the problem is most likely in line 17 (which is correct). |
The execution can take longer but now we know that the problem is most likely in line 17 (which is correct). |
||
[[Category:Debugger software]] |
Latest revision as of 00:47, 9 December 2022
The main documentation is available via |
Description | Content |
---|---|
module load devel/valgrind | |
Availability | bwUniCluster | BwForCluster_Chemistry |
License | GPL |
Citing | n/a |
Links | Valgrind Homepage |
Graphical Interface | No |
Introduction
Valgrind is an instrumentation framework for building dynamic analysis tools. The main (default) tool memcheck detects a wide variety of memory management bugs. This page introduces the various tools to fetch threading bugs, and profile your programs in detail. As such, any programmer must know valgrind's memcheck.
While the Linux distribution provides valgrind, this module comes with a newer version (which may interpret newer instruction sets) and more tools than the system provided one.
Overview
Valgrind ships with various tools, some of them are described in the following table.
Tool | Description |
---|---|
memcheck | Detects heap array over- and underruns, usage of uninitialized memory, memory leaks and incorrect freeing of heap memory. |
callgrind | Memory Profiler. Together with kcachegrind allows getting an overview of applications and getting details about memory access and costs. |
helgrind | Detects race conditions and deadlocks. |
drd | Detects race conditions. Does not detect deadlocks but needs less memory than helgrind. |
massif | A heap memory profiler showing the allocation history over time. |
Documentation
Online
Local
$ man valgrind
Usage
To simulate your program and gather information about it using a specific tool, valgrind can be called like this
$ valgrind --tool=<tool> --log-file=<logfile> ./example
For example to check for race conditions the command would look like this:
$ valgrind --tool=drd --log-file=log.mem ./example
Beware that the simulation via valgrind can take much longer and can consume much more memory compared to a normal execution.
Furthermore the tools can give false positives, i.e. they report errors even though the are none.
Example using drd on OpenMP
The following simple OpenMP-parallel example shows a data race on global data:
#include <stdlib.h>
#include <stdio.h>
#include "omp.h"
int global = 4711;
int main (int argc, char * argv[]) {
// The following is an ERROR: This should be a (thread-)local variable.
#pragma omp parallel
global = omp_get_thread_num();
printf("global:%d\n", global);
return EXIT_SUCCESS;
}
Compile this example using
$ gcc -Wall -O2 -fopenmp omp_error.c -o omp_error
One may optionally pass the -g to allow Valgrind to print source code lines in the erroneous functions.
Running this example shows:
$ valgrind --tool=drd ./omp_error ... ==1019408== Thread 2: ==1019408== Conflicting store by thread 2 at 0x00601034 size 4 ==1019408== at 0x4006D9: main._omp_fn.0 (openmp_error_access.c:13) ... ==1019408== Allocation context: Data section of /pfs/data5/home/es/es_es/es_rakeller/C/openmp_error_access ==1019408== Other segment start (thread 1) ==1019408== at 0x4C3F3CF: pthread_create_intercept (drd_pthread_intercepts.c:625) ==1019408== by 0x4C3F3CF: pthread_create@* (drd_pthread_intercepts.c:631) ==1019408== by 0x4E84A72: ??? (in /usr/lib64/libgomp.so.1.0.0) ==1019408== by 0x4E7A6A0: GOMP_parallel (in /usr/lib64/libgomp.so.1.0.0) ==1019408== by 0x4005C3: main (openmp_error_access.c:9) ==1019408== Other segment end (thread 1) ==1019408== at 0x4E86FAA: ??? (in /usr/lib64/libgomp.so.1.0.0) ==1019408== by 0x4E85A1C: ??? (in /usr/lib64/libgomp.so.1.0.0) ==1019408== by 0x4005C3: main (openmp_error_access.c:9) ==1019408== ==1019408== Thread 1: ==1019408== Conflicting load by thread 1 at 0x00601034 size 4 ==1019408== at 0x4005C4: main (openmp_error_access.c:15) ==1019408== Allocation context: Data section of /pfs/data5/home/es/es_es/es_rakeller/C/openmp_error_access ==1019408== Other segment start (thread 2) ...
Example for helgrind for PThreads
The following PThread-parallel example demonstrates how to detect data races in parallel programs.
/* pthreads.c */
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <math.h>
#define NUM_THREADS 2
int v = 0;
void* f(void* x)
{
int j = 0;
int k = *(int*)x;
for(j = 0; j < 100; j++)
v += sin(j) + 1 + k;
return NULL;
}
int main(int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int idx[NUM_THREADS];
int t;
for(t=0; t<NUM_THREADS; t++) {
idx[t] = t;
pthread_create(&threads[t], NULL, f, (void*)&idx[t]);
}
for(t=0; t<NUM_THREADS; t++)
pthread_join(threads[t], NULL);
printf("%i\n", v);
pthread_exit(NULL);
return 0;
}
Compile the program using
$ gcc -Wall -O2 pthreads.c -o pthreads -pthread -lm
where -pthread tells the compiler to link against the Pthreads library and -lm is needed for linking against the math library. This program has a race condition, consecutive executions can give different outputs. Such errors are hard to find because they can show up very rarely. Helgrind can tell you the problematic part of your code:
$ valgrind --tool=helgrind ./pthreads ... ==29237== ---------------------------------------------------------------- ==29237== ==29237== Possible data race during read of size 4 at 0x600C78 by thread #3 ==29237== Locks held: none ==29237== at 0x4007BC: f(void*) (in /pfs/data2/home/xx/xxxx/xxxx/pthreads) ==29237== by 0x4A0C0D4: mythread_wrapper (hg_intercepts.c:219) ==29237== by 0x3EDA6079D0: start_thread (in /lib64/libpthread-2.12.so) ==29237== by 0x3ED9AE8B6C: clone (in /lib64/libc-2.12.so) ==29237== ==29237== This conflicts with a previous write of size 4 by thread #2 ==29237== Locks held: none ==29237== at 0x4007FB: f(void*) (in /pfs/data2/home/xx/xxxx/xxxx/pthreads) ==29237== by 0x4A0C0D4: mythread_wrapper (hg_intercepts.c:219) ==29237== by 0x3EDA6079D0: start_thread (in /lib64/libpthread-2.12.so) ==29237== by 0x3ED9AE8B6C: clone (in /lib64/libc-2.12.so) ==29237== ==29237== ---------------------------------------------------------------- ...
Now we know that we have to check the function f for a possible data race. A similar output can be achieved using drd with the following command:
$ valgrind --tool=drd ./pthreads
Valgrind can give even better hints when compiled with debug information (helgrind produces similar output):
$ gcc -g -Wall pthreads.c -o pthreads -pthread -lm $ valgrind --tool=drd ./pthreads ... ==604== Thread 3: ==604== Conflicting load by thread 3 at 0x00600cc0 size 4 ==604== at 0x400749: f(void*) (pthreads.c:17) ==604== by 0x4A128B4: vgDrd_thread_wrapper (drd_pthread_intercepts.c:355) ==604== by 0x3EDA6079D0: start_thread (in /lib64/libpthread-2.12.so) ==604== by 0x3ED9AE8B6C: clone (in /lib64/libc-2.12.so) ==604== Allocation context: BSS section of fs/data2/home/xx/xxxx/xxxx/pthreads ==604== Other segment start (thread 2) ==604== (thread finished, call stack no longer available) ==604== Other segment end (thread 2) ==604== (thread finished, call stack no longer available) ...
The execution can take longer but now we know that the problem is most likely in line 17 (which is correct).