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.)
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.
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.
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.
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.
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";
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With