How to detect memory leaks and memory corruption

Valgrind will save you hours of debugging time spent on analysing memory corruption. With valgrind tools you can detect many memory management and threading bugs. This gives you a feel that your programs are free of many common bugs. You can find and eliminate bugs before they become a problem with valgrind. Valgrind is a debugging tool for large, complex programs.

When to use valgrind?

  • For small programs with short run-times, when developing you can always run the program under a valgrind tool (usually Memcheck), knowing that memory bugs will be found immediately.
  • In automatic testing. By using Valgrind tools in your automatic unit, integration, system you can be confident no code will be unchecked.
  • After big changes. To ensure new bugs haven’t been introduced in the new code.
  • When a bug occurs. Get instant feedback about t the bug , where it occurred, and why.

Examples:

Ex. //test.c

int main()
{
char *p=malloc(100);
}

$gcc -c val.c

$gcc -osingo val.o

$ valgrind –tool=memcheck ./singo

output:

==16405== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 12 from 1)

==16405== malloc/free: in use at exit: 100 bytes in 1 blocks.

==16405== malloc/free: 1 allocs, 0 frees, 100 bytes allocated.

==16405== For counts of detected errors, rerun with: -v

==16405== searching for pointers to 1 not-freed blocks.

If you have a memory leak, then the number of allocs and the number of frees will differ . If the number of allocs differs from the number of frees, you can rerun your program again with the leak-check option. This will show you all of the calls to malloc/new/etc that don’t have a matching free.
Compile your program with -g to include debugging information so that Memcheck’s error messages include exact line numbers.

$gcc -g -o val1 val1.c

$valgrind –tool=memcheck –leak-check=yes .val1

output:

==19466== malloc/free: in use at exit: 100 bytes in 1 blocks.

==19466== malloc/free: 1 allocs, 0 frees, 100 bytes allocated.

==19466== For counts of detected errors, rerun with: -v

==19466== searching for pointers to 1 not-freed blocks.

==19466== checked 47,596 bytes.

==19466==

==19466== LEAK SUMMARY:

==19466== definitely lost: 0 bytes in 0 blocks.

==19466== possibly lost: 0 bytes in 0 blocks.

==19466== still reachable: 100 bytes in 1 blocks.

==19466== suppressed: 0 bytes in 0 blocks.

==19466== Reachable blocks (those to which a pointer was found) are not shown.

==19466== To see them, rerun with: –leak-check=full –show-reachable=yes

Reading/writing off the end of malloc’d blocks

Valgrind can also find the use of invalid heap memory using the memcheck tool. For instance, if you allocate an array with malloc or new and then try to access a location past the end of the array:

Ex. //val.c

main()

{

char *p=malloc(100);

p[120]=’b’;

}

output:

==19489== Invalid write of size 1

==19489== at 0x80483EA: main (val1.c:6)

==19489== Address 0x40260A0 is not stack’d, malloc’d or (recently) free’d

Reading/writing memory after it has been free’d :

main()

{

char *p=malloc(100);

free(p);

p[23]=’b’;

}

output:

==2808== Invalid write of size 1

==2808== at 0x80483EA: main (val1.c:6)

==2808== Address 0x40270a0 is not stack’d, malloc’d or (recently) free’d

Use of uninitialized memory:

main()

{

int x;

x++;

printf(“%d”,x);

}

output:

==3276== Use of uninitialised value of size 4

==3276== at 0x3A27DB: _itoa_word (in /lib/libc-2.7.so)

==3276== by 0x3A673F: vfprintf (in /lib/libc-2.7.so)

==3276== by 0x3AC9B2: printf (in /lib/libc-2.7.so)

==3276== by 0x80483EB: main (in /home/lakshya/rima/a.out)

Reading/writing inappropriate areas on the stack

main()

{

int s;

int *p=&s;

p[-2]=7;

s=p[-20];

}

output:

==3313== Invalid read of size 4

==3313== at 0x80483BD: main (in /home/lakshya/rima/a.out)

==3313== Address 0xbeb5e5bc is just below the stack ptr. To suppress, use: –workaround-gcc296-bugs=yes

Overlapping src and dst pointers in memcpy() and related functions:

 

ex:

main()

{

char buf[1000];

char *ptr1=&buf[0];

char *ptr2=&buf[400];

memcpy(ptr1,ptr2,500); 

}

output:

==3362== Source and destination overlap in memcpy(0xBE9ED224, 0xBE9ED3B4, 500)

==3362== at 0x4007CB2: memcpy (mc_replace_strmem.c:402)

==3362== by 0x804840B: main (in /home/lakshya/rima/a.out)

Passing unaddressable bytes to a system call:

Ex:

main()

{

char *ptr=(char *)malloc(100);

read(0,ptr,500);

write(1,ptr,500);

}

output:

==3382== Syscall param read(buf) points to unaddressable byte(s)

==3382== at 0x42B343: __read_nocancel (in /lib/libc-2.7.so)

==3382== by 0x37D38F: (below main) (in /lib/libc-2.7.so)

==3382== Address 0x402708c is 0 bytes after a block of size 100 alloc’d

==3382== at 0x4005AC8: malloc (vg_replace_malloc.c:207)

==3382== by 0x8048440: main (in /home/lakshya/rima/a.out)

 

==3382== Syscall param write(buf) points to uninitialised byte(s)

==3382== at 0x42B3C3: __write_nocancel (in /lib/libc-2.7.so)

==3382== by 0x37D38F: (below main) (in /lib/libc-2.7.so)

==3382== Address 0x4027033 is 11 bytes inside a block of size 100 alloc’d

==3382== at 0x4005AC8: malloc (vg_replace_malloc.c:207)

==3382== by 0x8048440: main (in /home/lakshya/rima/a.out)

 

Mismatched use of malloc/new/new [] vs free/delete/delete []

#include “stdlib.h”

main()

{

int *ptr=new int;

free(ptr);

}

output:

==3426== Mismatched free() / delete / delete []

==3426== at 0x400566C: free (vg_replace_malloc.c:323)

==3426== by 0x80484EE: main (in /home/lakshya/rima/a.out)

==3426== Address 0x4028028 is 0 bytes inside a block of size 4 alloc’d

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s