Memory leak when using GString?

cat GString.c

#include <mcheck.h>
#include <glib.h>
#include <stdio.h>

int main(int argc, char **argv)
 {mtrace();
  fprintf(stderr, "GLib %u.%u.%u\n", glib_major_version, glib_minor_version, glib_micro_version);
  fprintf(stderr, "GCC  %ld\n", __STDC_VERSION__);
  if (argc > 1)
   {fprintf(stderr, "Allocate and free GString\n");
    GString *p = g_string_new("");
    g_string_free(p, 1);
   }
  else
   {fprintf(stderr, "Do nothing\n");
   }
  return 0;
 }
gcc -g -rdynamic -O0 -Wall -fstack-protector-strong -I/usr/include/glib-2.0/ -I/usr/lib/x86_64-linux-gnu/glib-2.0/include  -o "GString" GString.c -lglib-2.0
MALLOC_TRACE='zzz.txt' /home/phil/c/z/glib/GString
mtrace zzz.txt
  • GLib 2.56.4
  • GCC 201710
  • Do nothing
  • No memory leaks.
gcc -g -rdynamic -O0 -Wall -fstack-protector-strong -I/usr/include/glib-2.0/ -I/usr/lib/x86_64-linux-gnu/glib-2.0/include  -o "GString" GString.c -lglib-2.0
MALLOC_TRACE='zzz.txt' /home/phil/c/z/glib/GString 1
mtrace zzz.txt
  • GLib 2.56.4
  • GCC 201710
  • Allocate and free GString
Memory not freed:
-----------------
           Address     Size     Caller
0x00005653a3fe1600    0x1f0  at 0x7f5618ad60e7
0x00005653a3fe1a00    0x1f0  at 0x7f5618ad60e7
0x00005653a3fe1e00    0x1f0  at 0x7f5618ad60e7
0x00005653a3fe2200    0x1f0  at 0x7f5618ad60e7
1 Like

Probably you would get a more accurate idea of whether memory is leaked, by using valgrind along with the false-positives file that is shipped along with GLib. With just the mtrace information, not showing where the allocations happened, the information isn’t really actionable. (And do note that suppression of false positives is definitely needed, to effectively memory-profile GLib.)

You can use valgrind as:

valgrind --tool=memcheck --leak-check=full --leak-resolution=high --num-callers=50 --show-leak-kinds=definite --suppressions=/usr/share/glib-2.0/valgrind/glib.supp /home/phil/c/z/glib/GString 1

I have rerun with valgrind as you suggest with the specified suppressions to get the results below. valgrind reports:

still reachable: 18,604 bytes in 6 blocks

after creating and freeing a GString. Conversely, running a program that does nothing produces the more reassuring:

All heap blocks were freed – no leaks are possible

I think this indicates that mtrace is correct - there is unfreed memory present?

#include <glib.h>
int main(void)
{return 0;
}
==24388== Memcheck, a memory error detector
==24388== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==24388== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==24388== Command: /home/phil/c/z/glib/None
==24388==
==24388==
==24388== HEAP SUMMARY:
==24388== in use at exit: 0 bytes in 0 blocks
==24388== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==24388==
==24388== All heap blocks were freed -- no leaks are possible
==24388==
==24388== For counts of detected and suppressed errors, rerun with: -v
==24388== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
#include <glib.h>
#include <stdio.h>

int main(void)
{fprintf(stderr, "GLib %u.%u.%u\n", glib_major_version, glib_minor_version, glib_micro_version);
fprintf(stderr, "GCC %ld\n", __STDC_VERSION__);
fprintf(stderr, "Allocate and free GString\n");
GString *p = g_string_new("");
g_string_free(p, 1);
return 0;
}
==24392== Memcheck, a memory error detector
==24392== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==24392== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==24392== Command: /home/phil/c/z/glib/GString
==24392==
GLib 2.56.4
GCC 201710
Allocate and free GString
==24392==
==24392== HEAP SUMMARY:
==24392== in use at exit: 18,604 bytes in 6 blocks
==24392== total heap usage: 8 allocs, 2 frees, 18,632 bytes allocated
==24392==
==24392== LEAK SUMMARY:
==24392== definitely lost: 0 bytes in 0 blocks
==24392== indirectly lost: 0 bytes in 0 blocks
==24392== possibly lost: 0 bytes in 0 blocks
==24392== **still reachable: 18,604 bytes in 6 blocks**
==24392== suppressed: 0 bytes in 0 blocks
==24392== Reachable blocks (those to which a pointer was found) are not shown.
==24392== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==24392==
==24392== For counts of detected and suppressed errors, rerun with: -v
==24392== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

“Still reachable” does not imply a leak: it’s just memory that gets collected by the OS when the process terminates.

The important bits are the “definitely/indirectly/possibly lost” summaries.

See also: https://www.valgrind.org/docs/manual/faq.html#q-deflost

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.