Thursday, April 26, 2012

Using Valgrind Part 2

Using Memcheck tool of valgrind to detect memory leaks and other memory errors

Here is the demo program. You can try that. I have also attached it.

#include<stdio.h>
#include<stdlib.h>
void func()
{
int *f=(int *)malloc(sizeof(int)*10); ////Memory Leak
}
int main()
{
int *k;
int c;
int *p=(int *)malloc(sizeof(int));
free(p);
func();
c=*k;//use of uninitialized valirable
free(p);//double free
k=NULL;
printf("%d\n",*k);//accessing a null pointer
return 0;
}

Below is the valgrind memcheck tool output. I have added command also to use valgrind memcheck tool.
root@bt:~/Desktop# valgrind --tool=memcheck -v --leak-check=full --track-origins=yes ./a.out
==2230== Memcheck, a memory error detector
==2230== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==2230== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==2230== Command: ./a.out
==2230==
--2230-- Valgrind options:
--2230--    --tool=memcheck
--2230--    -v
--2230--    --leak-check=full
--2230--    --track-origins=yes
--2230-- Contents of /proc/version:
--2230--   Linux version 3.2.6 (root@bt) (gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5) ) #1 SMP Fri Feb 17 10:40:05 EST 2012
--2230-- Arch and hwcaps: X86, x86-sse1-sse2
--2230-- Page sizes: currently 4096, max supported 4096
--2230-- Valgrind library directory: /usr/local/lib/valgrind
--2230-- Reading syms from /lib/ld-2.11.1.so (0x4000000)
--2230--   Considering /lib/ld-2.11.1.so ..
--2230--   .. CRC mismatch (computed 45f50ae1 wanted 137bc614)
--2230--    object doesn't have a symbol table
--2230-- Reading syms from /root/Desktop/a.out (0x8048000)
--2230-- Reading syms from /usr/local/lib/valgrind/memcheck-x86-linux (0x38000000)
--2230--    object doesn't have a dynamic symbol table
--2230-- Reading suppressions file: /usr/local/lib/valgrind/default.supp
==2230== embedded gdbserver: reading from /tmp/vgdb-pipe-from-vgdb-to-2230-by-root-on-???
==2230== embedded gdbserver: writing to   /tmp/vgdb-pipe-to-vgdb-from-2230-by-root-on-???
==2230== embedded gdbserver: shared mem   /tmp/vgdb-pipe-shared-mem-vgdb-2230-by-root-on-???
==2230==
==2230== TO CONTROL THIS PROCESS USING vgdb (which you probably
==2230== don't want to do, unless you know exactly what you're doing,
==2230== or are doing some strange experiment):
==2230==   /usr/local/lib/valgrind/../../bin/vgdb --pid=2230 ...command...
==2230==
==2230== TO DEBUG THIS PROCESS USING GDB: start GDB like this
==2230==   /path/to/gdb ./a.out
==2230== and then give GDB the following command
==2230==   target remote | /usr/local/lib/valgrind/../../bin/vgdb --pid=2230
==2230== --pid is optional if only one valgrind process is running
==2230==
--2230-- Reading syms from /usr/local/lib/valgrind/vgpreload_core-x86-linux.so (0x4020000)
--2230-- Reading syms from /usr/local/lib/valgrind/vgpreload_memcheck-x86-linux.so (0x4023000)
--2230-- Reading syms from /lib/tls/i686/cmov/libc-2.11.1.so (0x4042000)
--2230--   Considering /lib/tls/i686/cmov/libc-2.11.1.so ..
--2230--   .. CRC mismatch (computed 2236eb0a wanted a071c0c3)
--2230--    object doesn't have a symbol table
--2230-- REDIR: 0x40b5b10 (rindex) redirected to 0x4027050 (rindex)
--2230-- REDIR: 0x40b1f40 (malloc) redirected to 0x40263bf (malloc)
--2230-- REDIR: 0x40b1e60 (free) redirected to 0x4025fd9 (free)
==2230== Use of uninitialised value of size 4
==2230==    at 0x8048499: main (hell1.c:14)
==2230==  Uninitialised value was created by a stack allocation
==2230==    at 0x8048471: main (hell1.c:8)
==2230==
==2230== Invalid free() / delete / delete[] / realloc()
==2230==    at 0x402605E: free (vg_replace_malloc.c:427)
==2230==    by 0x80484AA: main (hell1.c:15)
==2230==  Address 0x419d028 is 0 bytes inside a block of size 4 free'd
==2230==    at 0x402605E: free (vg_replace_malloc.c:427)
==2230==    by 0x804848F: main (hell1.c:12)
==2230==
==2230== Invalid read of size 4
==2230==    at 0x80484B7: main (hell1.c:17)
==2230==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==2230==
==2230==
==2230== Process terminating with default action of signal 11 (SIGSEGV)
==2230==  Access not within mapped region at address 0x0
==2230==    at 0x80484B7: main (hell1.c:17)
==2230==  If you believe this happened as a result of a stack
==2230==  overflow in your program's main thread (unlikely but
==2230==  possible), you can try to increase the size of the
==2230==  main thread stack using the --main-stacksize= flag.
==2230==  The main thread stack size used in this run was 8388608.
==2230==
==2230== HEAP SUMMARY:
==2230==     in use at exit: 40 bytes in 1 blocks
==2230==   total heap usage: 2 allocs, 2 frees, 44 bytes allocated
==2230==
==2230== Searching for pointers to 1 not-freed blocks
==2230== Checked 56,076 bytes
==2230==
==2230== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1
==2230==    at 0x4026444: malloc (vg_replace_malloc.c:263)
==2230==    by 0x8048465: func (hell1.c:5)
==2230==    by 0x8048494: main (hell1.c:13)
==2230==
==2230== LEAK SUMMARY:
==2230==    definitely lost: 40 bytes in 1 blocks
==2230==    indirectly lost: 0 bytes in 0 blocks
==2230==      possibly lost: 0 bytes in 0 blocks
==2230==    still reachable: 0 bytes in 0 blocks
==2230==         suppressed: 0 bytes in 0 blocks
==2230==
==2230== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 11 from 6)
==2230==
==2230== 1 errors in context 1 of 4:
==2230== Invalid read of size 4
==2230==    at 0x80484B7: main (hell1.c:17)
==2230==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==2230==
==2230==
==2230== 1 errors in context 2 of 4:
==2230== Invalid free() / delete / delete[] / realloc()
==2230==    at 0x402605E: free (vg_replace_malloc.c:427)
==2230==    by 0x80484AA: main (hell1.c:15)
==2230==  Address 0x419d028 is 0 bytes inside a block of size 4 free'd
==2230==    at 0x402605E: free (vg_replace_malloc.c:427)
==2230==    by 0x804848F: main (hell1.c:12)
==2230==
==2230==
==2230== 1 errors in context 3 of 4:
==2230== Use of uninitialised value of size 4
==2230==    at 0x8048499: main (hell1.c:14)
==2230==  Uninitialised value was created by a stack allocation
==2230==    at 0x8048471: main (hell1.c:8)
==2230==
--2230--
--2230-- used_suppression:     11 dl-hack3-cond-1
==2230==
==2230== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 11 from 6)
Segmentation fault
root@bt:~/Desktop#

You can clearly see that valgrind has pointed out commented errors and also display the detail description about that error.
Valgrind options     -     uses
--tool=memcheck        - using valgrind memcheck tool
--leak-check=full     - to see details of leaked memory
--track-origins=yes    - to see where uninitialised values come from
-v             - For counts of detected and suppressed errors

Memory Pools: describing and working with custom allocators

There are many different sorts of custom allocator, so Memcheck attempts to reason about them using a loose, abstract model. We use the following terminology when describing custom allocation systems:
• Custom allocation involves a set of independent "memory pools".
• Memcheck’s notion of a memory pool consists of a single "anchor address" and a set of non-overlapping "chunks" associated with the anchor address.
• Typically a pool’s anchor address is the address of a book-keeping "header" structure.
• Typically the pool’s chunks are drawn from a contiguous "superblock" acquired through the system malloc or mmap.

The Valgrind mempool client request API is intentionally vague about the exact structure of a mempool. There is no specific mention made of headers or superblocks.

Typically, before making client requests related to mempools, a client program will have allocated such a header and superblock for their mempool, and marked the superblock NOACCESS using the VALGRIND_MAKE_MEM_NOACCESS client request.
When dealing with mempools, the goal is to maintain a particular invariant condition: that Memcheck believes the unallocated portions of the pool’s superblock (including redzones) are NOACCESS. To maintain this invariant, the client program must ensure that the superblock starts out in that state; Memcheck cannot make it so, since Memcheck never explicitly learns about the superblock of a pool, only the allocated chunks within the pool.

Once the header and superblock for a pool are established and properly marked, there are a number of client requests programs can use to inform Memcheck about changes to the state of a mempool. e.g - VALGRIND_CREATE_MEMPOOL,VALGRIND_DESTROY_MEMPOOL,VALGRIND_MEMPOOL_ALLOC,VALGRIND_MEMPOOL_FREE, etc.

For details refer Valgrind Manual Page.

Debugging MPI Parallel Programs with Valgrind

Memcheck supports debugging of distributed-memory applications which use the MPI message passing standard. This support consists of a library of wrapper functions for the PMPI_* interface. When incorporated into the application’s address space, either by direct linking or by LD_PRELOAD, the wrappers intercept calls to PMPI_Send, PMPI_Recv, etc. They then use client requests to inform Memcheck of memory state changes caused by the function being wrapped.

For details refer valgrind Manual Page.

No comments:

Post a Comment