2.2.2.2 : How to use the valgrind's memcheck



This the command to be used to launch our hadamard_product_memory_leak program with valgrind :

valgrind ./hadamard_product_memory_leak 
==4738== Memcheck, a memory error detector
==4738== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==4738== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==4738== Command: ./hadamard_product_memory_leak
==4738== 
Hadamard product
tabResult[0] = 0
tabResult[0] = 0
tabResult[0] = 0
tabResult[0] = 0
tabResult[0] = 0
==4738== 
==4738== HEAP SUMMARY:
==4738==     in use at exit: 252,000 bytes in 15 blocks
==4738==   total heap usage: 17 allocs, 2 frees, 325,728 bytes allocated
==4738== 
==4738== LEAK SUMMARY:
==4738==    definitely lost: 252,000 bytes in 15 blocks
==4738==    indirectly lost: 0 bytes in 0 blocks
==4738==      possibly lost: 0 bytes in 0 blocks
==4738==    still reachable: 0 bytes in 0 blocks
==4738==         suppressed: 0 bytes in 0 blocks
==4738== Rerun with --leak-check=full to see details of leaked memory
==4738== 
==4738== For counts of detected and suppressed errors, rerun with: -v
==4738== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)


The report is quite small but we have some informations.

First, our program allocates 325728 bytes durring its execution (this can be much more than the total RAM is there are some reallocation or multiple new/delete during the execution. And our program calls 17 times malloc and only 2 times free (so we missed 15 frees) :



==4738== HEAP SUMMARY:
==4738==     in use at exit: 252,000 bytes in 15 blocks
==4738==   total heap usage: 17 allocs, 2 frees, 325,728 bytes allocated


Then, we have directly the number of bytes lost by the memory leak, here 252000 bytes :

==4738== LEAK SUMMARY:
==4738==    definitely lost: 252,000 bytes in 15 blocks
==4738==    indirectly lost: 0 bytes in 0 blocks
==4738==      possibly lost: 0 bytes in 0 blocks
==4738==    still reachable: 0 bytes in 0 blocks
==4738==         suppressed: 0 bytes in 0 blocks


We still do not have the detail of the leak but valgrind invites us to rerun our program with the option --leak-check=full to get more informations about the memory leak :

==4738== Rerun with --leak-check=full to see details of leaked memory


So, let's do that :

valgrind --leak-check=full ./hadamard_product_memory_leak 
==4801== Memcheck, a memory error detector
==4801== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==4801== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==4801== Command: ./hadamard_product_memory_leak
==4801== 
Hadamard product
tabResult[0] = 0
tabResult[0] = 0
tabResult[0] = 0
tabResult[0] = 0
tabResult[0] = 0
==4801== 
==4801== HEAP SUMMARY:
==4801==     in use at exit: 252,000 bytes in 15 blocks
==4801==   total heap usage: 17 allocs, 2 frees, 325,728 bytes allocated
==4801== 
==4801== 4,000 bytes in 1 blocks are definitely lost in loss record 1 of 15
==4801==    at 0x4C3089F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4801==    by 0x10906F: evaluateHadamardProduct(unsigned long) (main.cpp:28)
==4801==    by 0x108CF1: main (main.cpp:44)
==4801== 
==4801== 4,000 bytes in 1 blocks are definitely lost in loss record 2 of 15
==4801==    at 0x4C3089F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4801==    by 0x10907A: evaluateHadamardProduct(unsigned long) (main.cpp:29)
==4801==    by 0x108CF1: main (main.cpp:44)
==4801== 
==4801== 4,000 bytes in 1 blocks are definitely lost in loss record 3 of 15
==4801==    at 0x4C3089F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4801==    by 0x109085: evaluateHadamardProduct(unsigned long) (main.cpp:30)
==4801==    by 0x108CF1: main (main.cpp:44)
==4801== 
==4801== 8,000 bytes in 1 blocks are definitely lost in loss record 4 of 15
==4801==    at 0x4C3089F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4801==    by 0x10906F: evaluateHadamardProduct(unsigned long) (main.cpp:28)
==4801==    by 0x108CFB: main (main.cpp:45)
==4801== 
==4801== 8,000 bytes in 1 blocks are definitely lost in loss record 5 of 15
==4801==    at 0x4C3089F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4801==    by 0x10907A: evaluateHadamardProduct(unsigned long) (main.cpp:29)
==4801==    by 0x108CFB: main (main.cpp:45)
==4801== 
==4801== 8,000 bytes in 1 blocks are definitely lost in loss record 6 of 15
==4801==    at 0x4C3089F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4801==    by 0x109085: evaluateHadamardProduct(unsigned long) (main.cpp:30)
==4801==    by 0x108CFB: main (main.cpp:45)
==4801== 
==4801== 12,000 bytes in 1 blocks are definitely lost in loss record 7 of 15
==4801==    at 0x4C3089F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4801==    by 0x10906F: evaluateHadamardProduct(unsigned long) (main.cpp:28)
==4801==    by 0x108D05: main (main.cpp:46)
==4801== 
==4801== 12,000 bytes in 1 blocks are definitely lost in loss record 8 of 15
==4801==    at 0x4C3089F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4801==    by 0x10907A: evaluateHadamardProduct(unsigned long) (main.cpp:29)
==4801==    by 0x108D05: main (main.cpp:46)
==4801== 
==4801== 12,000 bytes in 1 blocks are definitely lost in loss record 9 of 15
==4801==    at 0x4C3089F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4801==    by 0x109085: evaluateHadamardProduct(unsigned long) (main.cpp:30)
==4801==    by 0x108D05: main (main.cpp:46)
==4801== 
==4801== 20,000 bytes in 1 blocks are definitely lost in loss record 10 of 15
==4801==    at 0x4C3089F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4801==    by 0x10906F: evaluateHadamardProduct(unsigned long) (main.cpp:28)
==4801==    by 0x108D0F: main (main.cpp:47)
==4801== 
==4801== 20,000 bytes in 1 blocks are definitely lost in loss record 11 of 15
==4801==    at 0x4C3089F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4801==    by 0x10907A: evaluateHadamardProduct(unsigned long) (main.cpp:29)
==4801==    by 0x108D0F: main (main.cpp:47)
==4801== 
==4801== 20,000 bytes in 1 blocks are definitely lost in loss record 12 of 15
==4801==    at 0x4C3089F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4801==    by 0x109085: evaluateHadamardProduct(unsigned long) (main.cpp:30)
==4801==    by 0x108D0F: main (main.cpp:47)
==4801== 
==4801== 40,000 bytes in 1 blocks are definitely lost in loss record 13 of 15
==4801==    at 0x4C3089F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4801==    by 0x10906F: evaluateHadamardProduct(unsigned long) (main.cpp:28)
==4801==    by 0x108D19: main (main.cpp:48)
==4801== 
==4801== 40,000 bytes in 1 blocks are definitely lost in loss record 14 of 15
==4801==    at 0x4C3089F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4801==    by 0x10907A: evaluateHadamardProduct(unsigned long) (main.cpp:29)
==4801==    by 0x108D19: main (main.cpp:48)
==4801== 
==4801== 40,000 bytes in 1 blocks are definitely lost in loss record 15 of 15
==4801==    at 0x4C3089F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4801==    by 0x109085: evaluateHadamardProduct(unsigned long) (main.cpp:30)
==4801==    by 0x108D19: main (main.cpp:48)
==4801== 
==4801== LEAK SUMMARY:
==4801==    definitely lost: 252,000 bytes in 15 blocks
==4801==    indirectly lost: 0 bytes in 0 blocks
==4801==      possibly lost: 0 bytes in 0 blocks
==4801==    still reachable: 0 bytes in 0 blocks
==4801==         suppressed: 0 bytes in 0 blocks
==4801== 
==4801== For counts of detected and suppressed errors, rerun with: -v
==4801== ERROR SUMMARY: 15 errors from 15 contexts (suppressed: 0 from 0)


Here we have more verbosity about memory leak.

Of course, valgrind cannot give us the line that do not deallocate the data because there are none but it gives us the lines which does the memory allocation that we do not deallocate :



==4801== 4,000 bytes in 1 blocks are definitely lost in loss record 1 of 15
==4801==    at 0x4C3089F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4801==    by 0x10906F: evaluateHadamardProduct(unsigned long) (main.cpp:28)
==4801==    by 0x108CF1: main (main.cpp:44)


For example here, line 28 of file main.cpp :

1
float * tabResult = new float[nbElement];


And the same of lines 29 and 30 each time we do an allocation (so five times for each in our case).

So, we have to add code to deallocate the pointer from these lines :



The evaluateHadamardProduct function must be changed into :



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void evaluateHadamardProduct(long unsigned int nbElement){
	//Allocation of the tables
	float * tabResult = new float[nbElement];
	float * tabX = new float[nbElement];
	float * tabY = new float[nbElement];
	//Initialisation of the tables
	for(long unsigned int i(0lu); i < nbElement; ++i){
		tabX[i] = (float)(i*32lu%17lu);
		tabY[i] = (float)(i*57lu%31lu);
	}
	//Do the hadamard product
	hadamard_product(tabResult, tabX, tabY, nbElement);
	
	cout << "tabResult[0] = " << tabResult[0] << endl;
	
	//Deallocation of the tables
	delete [] tabResult;
	delete [] tabX;
	delete [] tabY;
}


Then we recompile :

1
2
3
4
5
make
Scanning dependencies of target hadamard_product_memory_leak
[ 50%] Building CXX object CMakeFiles/hadamard_product_memory_leak.dir/main.cpp.o
[100%] Linking CXX executable hadamard_product_memory_leak
[100%] Built target hadamard_product_memory_leak


And the execution is good :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
valgrind ./hadamard_product_memory_leak 
==4895== Memcheck, a memory error detector
==4895== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==4895== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==4895== Command: ./hadamard_product_memory_leak
==4895== 
Hadamard product
tabResult[0] = 0
tabResult[0] = 0
tabResult[0] = 0
tabResult[0] = 0
tabResult[0] = 0
==4895== 
==4895== HEAP SUMMARY:
==4895==     in use at exit: 0 bytes in 0 blocks
==4895==   total heap usage: 17 allocs, 17 frees, 325,728 bytes allocated
==4895== 
==4895== All heap blocks were freed -- no leaks are possible
==4895== 
==4895== For counts of detected and suppressed errors, rerun with: -v
==4895== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)


The memory leak is solved.


Now, take the habit to run your programs with valgrind and be sure that you get :


1
2
3
4
5
6
7
8
==4895== HEAP SUMMARY:
==4895==     in use at exit: 0 bytes in 0 blocks
==4895==   total heap usage: 17 allocs, 17 frees, 325,728 bytes allocated
==4895== 
==4895== All heap blocks were freed -- no leaks are possible
==4895== 
==4895== For counts of detected and suppressed errors, rerun with: -v
==4895== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)


You must have the line :

1
==4895== All heap blocks were freed -- no leaks are possible


So you can be sure there is no technical issue in your program.