You can download the zip for the code below here
Valgrind is a dynamic code analyzer software. This is a tool to help developpers with memory debugging, leak detection, and code profiling.
It was created in 2000 by Julian Seward and it aimed to be a free version of Purify (another code analyzer). This tool was initialy built to Linux x86 but it is now a generic framework.
It is mostly used for C and C++ languages, but cause it analyzes the compiled executable, it can work with other languages. Since it has become a framework, some modules (extensions) were created. For example cachegrind (caches errors) and hellgrind (threads errors).
A gui named Valkyrie was developped, but we will only work in command line.
First, we need to install Valgrind. You can perform the installation with this very complicated command line :
$ apt install valgrind
You can check valgrind's website here for more informations. You can also take a look at the man documentation reachable below.
$ man valgrind
Compile the code
$ gcc main.c -o main
Run valgrind
$ valgrind ./main
For each example below, you must compile and execute the binary using valgrind, read the report and understand what the issue is and how it is detected.
#include <stdlib.h>
int main(void)
{
int *p = malloc(sizeof *p);
*p = 10;
p = NULL;
return 0;
}
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int *p = malloc(sizeof *p);
if (p != NULL)
{
*p = 180;
printf("\nValue before free = %d\n", *p);
free(p);
printf("\nValue after free = %d\n", *p);
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int *p = malloc(3 * sizeof *p);
if (p != NULL)
{
printf("\nWriting index 3\n");
p[3] = 0;
printf("\nWriting index -1\n");
p[-1] = 0;
free(p);
}
return 0;
}
#include <stdio.h>
int main(void)
{
int i;
if (i)
{
printf("Hello, world !\n");
}
return 0;
}
#include <unistd.h>
#include <stdlib.h>
int main( void )
{
char* arr = malloc(10);
(void) write( 1 /* stdout */, arr, 10 );
return 0;
}
#include <stdlib.h>
#include <string.h>
int main(void)
{
char* arr2 = malloc(20);
char* arr1 = malloc(10);
memcpy(arr1, arr2, 15);
return 0;
}
#include <stdlib.h>
int main(void)
{
int *p = NULL;
*p = 0;
return 0;
}
Compile and execute the code below (without then with valgrind):
#include <stdio.h>
#include <stdlib.h>
void f(int a, int b)
{
int *p1, *p2, *p3;
p1 = (int*) malloc(sizeof(int));
printf("\nmalloc p1 at %p\n", p1);
*p1 = a;
p2 = p1;
if(a > b)
{
printf("\nfree p1 at %p\n", p1);
free(p1);
}
p3 = (int*) malloc(sizeof(int));
printf("\nmalloc p3 at %p\n", p3);
*p3 = b;
printf("\n%d\n", *p2);
free(p3);
}
void main()
{
// detected
f(5, 4);
// not trigerring - not detected
//f(3, 4);
}
In the first time compile and execute without valgrind !
You can just type words to guess like :
Everything seems fine ? Now execute it with valgrind.
What can you see ?
You can try to find the issue and fix it if you feel like ( it's not that hard :p )