You are not logged in.

#1 2018-10-30 15:57:37

grininmonkey
Member
Registered: 2018-09-29
Posts: 34

C - linking FreeType memory leaks?

I have to apologize up front on my limited knowledge all around as I am working on my very first C program and many things are very new to me.... but have run into an (issue?) which I am not certain on where and how to fix it or if its something I can safely ignore?

Recently after the upgrade came in for valgrind from version 3.13 to 3.14 my project was suddenly reporting leaks with the output trace starting with ??? (in /usr/lib/ld-2.28.so).... after some poking around I narrowed it down to a possible issue with either the new version of valgrind (maybe some new args I need to pass?) or freetype2 2.9.1-1 itself and not sure which it is.

The following is a straight forward simple test of just adding -lfreetype flag to gcc and then running valgrind 3.14 ... My project was reporting 18,604 bytes in 6 blocks Leaked in the summary which matches the summary output below

~/Projects/C/testing$ cat testft.c
int
main()
{


	return 0;

}
 ~/Projects/C/testing$ gcc -o testft testft.c -lfreetype
 ~/Projects/C/testing$ valgrind --leak-check=full --show-leak-kinds=all ./testft
==3683== Memcheck, a memory error detector
==3683== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==3683== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==3683== Command: ./testft
==3683== 
==3683== 
==3683== HEAP SUMMARY:
==3683==     in use at exit: 18,604 bytes in 6 blocks
==3683==   total heap usage: 6 allocs, 0 frees, 18,604 bytes allocated
==3683== 
==3683== 4 bytes in 1 blocks are still reachable in loss record 1 of 6
==3683==    at 0x483777F: malloc (vg_replace_malloc.c:299)
==3683==    by 0x51CE5B3: ??? (in /usr/lib/libglib-2.0.so.0.5800.1)
==3683==    by 0x51CE6AB: g_private_get (in /usr/lib/libglib-2.0.so.0.5800.1)
==3683==    by 0x51F814D: g_slice_alloc (in /usr/lib/libglib-2.0.so.0.5800.1)
==3683==    by 0x523367E: g_hash_table_new_full (in /usr/lib/libglib-2.0.so.0.5800.1)
==3683==    by 0x520CEE3: ??? (in /usr/lib/libglib-2.0.so.0.5800.1)
==3683==    by 0x4010549: call_init.part.0 (in /usr/lib/ld-2.28.so)
==3683==    by 0x4010649: _dl_init (in /usr/lib/ld-2.28.so)
==3683==    by 0x4002039: ??? (in /usr/lib/ld-2.28.so)
==3683== 
==3683== 32 bytes in 1 blocks are still reachable in loss record 2 of 6
==3683==    at 0x4839B65: calloc (vg_replace_malloc.c:752)
==3683==    by 0x52172A9: g_malloc0 (in /usr/lib/libglib-2.0.so.0.5800.1)
==3683==    by 0x52336E7: g_hash_table_new_full (in /usr/lib/libglib-2.0.so.0.5800.1)
==3683==    by 0x520CEE3: ??? (in /usr/lib/libglib-2.0.so.0.5800.1)
==3683==    by 0x4010549: call_init.part.0 (in /usr/lib/ld-2.28.so)
==3683==    by 0x4010649: _dl_init (in /usr/lib/ld-2.28.so)
==3683==    by 0x4002039: ??? (in /usr/lib/ld-2.28.so)
==3683== 
==3683== 64 bytes in 1 blocks are still reachable in loss record 3 of 6
==3683==    at 0x4839B65: calloc (vg_replace_malloc.c:752)
==3683==    by 0x52172A9: g_malloc0 (in /usr/lib/libglib-2.0.so.0.5800.1)
==3683==    by 0x52336D1: g_hash_table_new_full (in /usr/lib/libglib-2.0.so.0.5800.1)
==3683==    by 0x520CEE3: ??? (in /usr/lib/libglib-2.0.so.0.5800.1)
==3683==    by 0x4010549: call_init.part.0 (in /usr/lib/ld-2.28.so)
==3683==    by 0x4010649: _dl_init (in /usr/lib/ld-2.28.so)
==3683==    by 0x4002039: ??? (in /usr/lib/ld-2.28.so)
==3683== 
==3683== 88 bytes in 1 blocks are still reachable in loss record 4 of 6
==3683==    at 0x483777F: malloc (vg_replace_malloc.c:299)
==3683==    by 0x52172F1: g_malloc (in /usr/lib/libglib-2.0.so.0.5800.1)
==3683==    by 0x51F8174: g_slice_alloc (in /usr/lib/libglib-2.0.so.0.5800.1)
==3683==    by 0x523367E: g_hash_table_new_full (in /usr/lib/libglib-2.0.so.0.5800.1)
==3683==    by 0x520CEE3: ??? (in /usr/lib/libglib-2.0.so.0.5800.1)
==3683==    by 0x4010549: call_init.part.0 (in /usr/lib/ld-2.28.so)
==3683==    by 0x4010649: _dl_init (in /usr/lib/ld-2.28.so)
==3683==    by 0x4002039: ??? (in /usr/lib/ld-2.28.so)
==3683== 
==3683== 2,032 bytes in 1 blocks are still reachable in loss record 5 of 6
==3683==    at 0x4839B65: calloc (vg_replace_malloc.c:752)
==3683==    by 0x52172A9: g_malloc0 (in /usr/lib/libglib-2.0.so.0.5800.1)
==3683==    by 0x51F83CE: g_slice_alloc (in /usr/lib/libglib-2.0.so.0.5800.1)
==3683==    by 0x523367E: g_hash_table_new_full (in /usr/lib/libglib-2.0.so.0.5800.1)
==3683==    by 0x520CEE3: ??? (in /usr/lib/libglib-2.0.so.0.5800.1)
==3683==    by 0x4010549: call_init.part.0 (in /usr/lib/ld-2.28.so)
==3683==    by 0x4010649: _dl_init (in /usr/lib/ld-2.28.so)
==3683==    by 0x4002039: ??? (in /usr/lib/ld-2.28.so)
==3683== 
==3683== 16,384 bytes in 1 blocks are still reachable in loss record 6 of 6
==3683==    at 0x483777F: malloc (vg_replace_malloc.c:299)
==3683==    by 0x52172F1: g_malloc (in /usr/lib/libglib-2.0.so.0.5800.1)
==3683==    by 0x520CEF5: ??? (in /usr/lib/libglib-2.0.so.0.5800.1)
==3683==    by 0x4010549: call_init.part.0 (in /usr/lib/ld-2.28.so)
==3683==    by 0x4010649: _dl_init (in /usr/lib/ld-2.28.so)
==3683==    by 0x4002039: ??? (in /usr/lib/ld-2.28.so)
==3683== 
==3683== LEAK SUMMARY:
==3683==    definitely lost: 0 bytes in 0 blocks
==3683==    indirectly lost: 0 bytes in 0 blocks
==3683==      possibly lost: 0 bytes in 0 blocks
==3683==    still reachable: 18,604 bytes in 6 blocks
==3683==         suppressed: 0 bytes in 0 blocks
==3683== 
==3683== For counts of detected and suppressed errors, rerun with: -v
==3683== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
~/Projects/C/testing$ 

Last edited by grininmonkey (2018-10-30 16:10:33)

Offline

#2 2018-10-30 20:39:21

hpmachining
Member
From: Michigan
Registered: 2016-11-23
Posts: 40
Website

Re: C - linking FreeType memory leaks?

grininmonkey wrote:

I am not certain on where and how to fix it or if its something I can safely ignore?

Generally speaking, "still reachable" warnings can be safely ignored. They don't refer to "true" memory leaks where a pointer is no longer available to free memory while the program is running. Still reachable means that a pointer to the allocated memory is still available when the program exits, so it could have been freed before exiting, but wasn't. Your test program itself doesn't do anything, so it is not the cause of the warnings.

Offline

#3 2018-10-31 10:30:24

mxfm
Member
Registered: 2015-10-23
Posts: 163

Re: C - linking FreeType memory leaks?

1. Some memory is allocated by C runtime before main() function. By the way, this changes not because of updating valgrind package, but C runtime. These messages can be ignored.
2. Valgrind sometimes may issue false positive errors. Usually, it is a waste of time to debug certainly valid programs for the purpose to find some 'errors' in language runtime. May be there are good reasons for such behavior.

Offline

#4 2018-10-31 11:34:29

grininmonkey
Member
Registered: 2018-09-29
Posts: 34

Re: C - linking FreeType memory leaks?

Thanks for the replies!

I had the feeling things where "ok" as long as nothing is reported in the lost types, but wanted to make sure I wasn't missing something I didn't quite know yet....  what threw me off I guess, was that I was maintaining a valgrind output of "All heap blocks were freed -- no leaks are possible" with my project, but now it constantly reports what I posted and was worried I broke something in my project.

Offline

#5 2018-10-31 18:54:29

jjacky
Member
Registered: 2011-11-09
Posts: 347
Website

Re: C - linking FreeType memory leaks?

Note that since you know those reported leaks come from simply linking to freetype, what you can do is create a suppressions file. That is, create such a minimal program as you did then run valgrind and ask for all suppressions to be generated, e.g:

valgrind --leak-check=full --show-leak-kinds=all --gen-suppressions=all --log-file=log ./testft

You then need to edit the file "log" to only keep suppressions. One way to do it could be using the following script:

#!/usr/bin/perl

# Copyright 2016 Timothe Litt litt at acm _ddot_ org
#
# May be freely used and copied providing this notice is retained
# No warranty, use at your own risk
#

# valgrind --leak-check=full --show-leak-kinds=all --gen-suppressions=all -- \
#   foo 3>&1 1>&2 2>&3 | grindmerge -f rules > rules.new

use warnings;
use strict;

use Digest::MD5 qw/md5_hex/;

my %known;
my $dups = 0;

sub parse {
    my $in = shift;

    while( <$in> ) {
        next unless( /^\{/ );

        my $block = $_;
        while( <$in> ) {
            if( /^\}/ ) {
                $block .= "}\n";
                last;
            }
            $block .= $_;
        }
        last unless( defined $block );
        if( $block !~ /\}\n/ ) {
            print STDERR ("Unterminated suppression at line $.\n" );
            last;
        }
        my $key = $block;
        $key =~ s/(\A\{[^\n]*\n)\s*[^\n]*\n/$1/;
        my $sum = md5_hex( $key );
        $dups++ if( exists $known{$sum} );
        $known{$sum} = $block;
    }
}

if( @ARGV >= 2 && $ARGV[0] eq '-f' ) {
    if( open( my $db, '<', $ARGV[1] ) ) {
        parse( $db );
        close( $db );
    } else {
        print STDERR ("Open failed for $ARGV[1]: $!\n");
        exit 1;
    }
    print STDERR ("Read " . keys( %known ) . " suppressions from $ARGV[1]\n" );
}

parse( \*STDIN );

print $known{$_} foreach ( sort keys %known );

print STDERR ("Squashed $dups duplicate suppressions\n")

You can then just use

grindmerge <log >freetype.supp

In such a case you might be fine using them as-is, other times it might be needed to edit them a bit. (Lots of reading available about suppressions in the manual and elsewhere.  Though I don't use wxgtk I found this page to be a nice read. I also believe the script above comes from there.)
After that, when using valgrind on your project make sure to add --suppressions=freetype.supp (or add it to either ~/.valgrindrc or ./.valgrindrc) and the report should put those aside as suppressed, e.g:

==32003== HEAP SUMMARY:
==32003==     in use at exit: 18,604 bytes in 6 blocks
==32003==   total heap usage: 6 allocs, 0 frees, 18,604 bytes allocated
==32003== 
==32003== LEAK SUMMARY:
==32003==    definitely lost: 0 bytes in 0 blocks
==32003==    indirectly lost: 0 bytes in 0 blocks
==32003==      possibly lost: 0 bytes in 0 blocks
==32003==    still reachable: 0 bytes in 0 blocks
==32003==         suppressed: 18,604 bytes in 6 blocks

Might make it easier to see if there are leaks from your own code or not.

Also, for the record, in this case the code in question comes from glib2 (which must be used by freetype). It might also be good to know, when working with glib (even indirectly as here), that the packages comes with a suppressions file (/usr/share/glib-2.0/valgrind/glib.supp) that can be used. Even though in this case it wouldn't have helped it seems, since those aren't covered by the suppressions file. This outta do it though:

{
   glib-init-malloc
   Memcheck:Leak
   match-leak-kinds: reachable
   fun:malloc
   ...
   fun:g_quark_init
   ...
   fun:glib_init_ctor
}
{
   glib-init-calloc
   Memcheck:Leak
   match-leak-kinds: reachable
   fun:calloc
   ...
   fun:g_quark_init
   ...
   fun:glib_init_ctor
}

(Note: I've sent it upstream.)

Offline

Board footer

Powered by FluxBB