Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Interpret Valgrind's trace-malloc output

Valgrind is an excellent memory debugger, and it has the option --trace-malloc=yes, which produces something like this:

--16301-- malloc(8) = 0x4EAD748
--16301-- free(0x4EAD748)
--16301-- free(0x4EAD498)
--16301-- malloc(21) = 0x4EAD780
--16301-- malloc(8) = 0x4EAD838
--16301-- free(0x4EAD6F8)
--16301-- calloc(1,88) = 0x4EAD870
--16301-- realloc(0x0,160)malloc(160) = 0x4EB1CF8
--16301-- realloc(0x4EB9F28,4) = 0x4EBA060

Is there a tool that parses this output and tells me for each address whether it's not been correctly allocated and freed in a matching pair?

GCC has something similar with the mtrace() function and the mtrace command-line tool, but the format is different.

Bonus question: Is it possible to output the actual address next to a "definitely lost" statement?

(I'm tagging this "C" and "C++" for the two languages most likely to be used with Valgrind.)

like image 972
Kerrek SB Avatar asked Jan 05 '12 23:01

Kerrek SB


People also ask

What does valgrind return?

By default Valgrind's malloc, realloc, etc, return a block whose starting address is 8-byte aligned or 16-byte aligned (the value depends on the platform and matches the platform default). This option allows you to specify a different alignment.

How do I track valgrind errors?

If you compile your program with the -g flag, Valgrind will show you the function names and line numbers where errors occur. Sometimes the actual bug occurs on a different line (particularly for uninitialized value errors) but the line number Valgrind tells you is a good starting point.

How does valgrind detect memory leaks?

Detecting memory leaks with Valgrind MemcheckMemcheck tracks all memory reads, writes, allocations, and deallocations in a C or C++ program. The tool can detect many different memory errors. For instance, it detects reads or writes before or after allocated memory blocks.

How do you check valgrind logs?

If you give the -v option, Valgrind will print the list of used suppressions at the end of execution. For a leak suppression, this output gives the number of different loss records that match the suppression, and the number of bytes and blocks suppressed by the suppression.


1 Answers

The output seems to be a partial output (or it is from hideously broken code. However, this seems to be a jobby for a simple perl script matching up the address. Actually, with C++2011's regular expressions even C++ should be up to the task but I haven't used these, yet. So, here is a simple (although probably rather clumsy) perl script reading valgrind's output from standard input:

 #!/usr/bin/perl -w
use strict;

my %allocated;

while (<>)
  {
    chomp;
    if (/(realloc\(([^,]*),([^)]*)\)).* = (.*)/)
      {
        if ($2 ne "0x0")
          {
            if (!exists $allocated{$2})
              {
                print "spurious realloc($2, $3) = $4\n";
              }
            else
              {
                delete $allocated{$2};
              }
          }
        $allocated{$4} = "$1$;$3";
      }
    elsif (/(malloc\((.*)\)) = (.*)/)
      {
        $allocated{$3} = "$1$;$2";
      }
    elsif (/ free\((.*)\)/)
      {
        if ($1 ne "0x0")
          {
            if (!exists $allocated{$1})
              {
                print "spurious free($1)\n";
              }
            else
              {
                delete $allocated{$1};
              }
          }
      }
    elsif (/(calloc\((.*),(.*)\)) = (.*)/)
      {
        $allocated{$4} = "$1$;" . ($2 * $3);
      }
  }

my $total = 0;
foreach my $leak (keys %allocated)
  {
    my($call, $size) = split(/$;/, $allocated{$leak});
    print "leak: address=$leak source=$call size=$size\n";
    $total += $size;
  }

if (0 < $total)
  {
    print "total leak=$total\n";
  }
like image 198
Dietmar Kühl Avatar answered Oct 12 '22 21:10

Dietmar Kühl