Memory leak with basic TTree

No, I don’t think so. When I wrap the repro() function in a main() and compile the file, I also get no memory increase, even if I use the same ROOT version as you on lxplus (6.20.04).

Hi,

I ran the following command :

valgrind ./run --suppression=/etc/root/valgrind-root.supp

Unfortunately I still get the exact same valgrind output !
Even using the code from the GitHub rep…

Corentin

I guess the order matters:
valgrind --suppressions=/etc/root/valgrind-root.supp ./run

Well, this still doesn’t work :

valgrind --suppressions=/etc/root/valgrind-root.supp ./run
(with a ‘s’ at the end of suppressionS :wink:, my mistake)

But still same behavior unfortunately…

In the first post, you mention “errors” (often hundreds of them) that have been present in ROOT for a long time.
You can easily see them with the “root.exe”:
valgrind --suppressions=/etc/root/valgrind-root.supp /usr/bin/root.exe -q -l

Yes, exactly these errors happen in general when you start a ROOT process. I think this is just from memory that ROOT allocates where valgrind can’t tell that it’s freed up in the end, even though we try our best to suppress these false positives with the suppression file.

Your code doesn’t have any leaks, as you can verify by running it in a loop many times and tracking the memory resident set size as I suggest. Sorry for this unsatisfying answer :slight_smile:

And valgrind actually reports it as such, and we are missing info from your side:

“definitely lost” and “indirectly lost” are those we must fix; there are not many and these might be covered by the suppressions file.

2048 errors, on the other hand, is worrying - unless they are all gone with the help of the suppression file. Could you post an example of an error that’s left after applying the suppression file? (In case you wonder: I’m checking this regularly and I don’t see any errors in current master, with the - simple - tests I run.)

For ROOT 6.26/04 (your binary distribution) on Ubuntu 22.04 / x86_64, I get two “Invalid read of size 8” (4 errors from 2 contexts) related to “dl_open”:

valgrind --suppressions=$(root-config --etcdir)/valgrind-root.supp $(root-config --bindir)/root.exe -q -l

==23097== Memcheck, a memory error detector
==23097== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==23097== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==23097== Command: /.../root_v6.26.04/bin/root.exe -q -l
==23097== 
==23097== Invalid read of size 8
==23097==    at 0x40286C8: strncmp (strcmp.S:172)
==23097==    by 0x400668D: is_dst (dl-load.c:216)
==23097==    by 0x400810E: _dl_dst_count (dl-load.c:253)
==23097==    by 0x400810E: expand_dynamic_string_token (dl-load.c:395)
==23097==    by 0x40082B7: fillin_rpath.isra.0 (dl-load.c:483)
==23097==    by 0x4008602: decompose_rpath (dl-load.c:654)
==23097==    by 0x400ABF5: cache_rpath (dl-load.c:696)
==23097==    by 0x400ABF5: cache_rpath (dl-load.c:677)
==23097==    by 0x400ABF5: _dl_map_object (dl-load.c:2165)
==23097==    by 0x4003494: openaux (dl-deps.c:64)
==23097==    by 0x5225C27: _dl_catch_exception (dl-error-skeleton.c:208)
==23097==    by 0x4003C7B: _dl_map_object_deps (dl-deps.c:248)
==23097==    by 0x400EA0E: dl_open_worker_begin (dl-open.c:592)
==23097==    by 0x5225C27: _dl_catch_exception (dl-error-skeleton.c:208)
==23097==    by 0x400DF99: dl_open_worker (dl-open.c:782)
==23097==    by 0x5225C27: _dl_catch_exception (dl-error-skeleton.c:208)
==23097==    by 0x400E34D: _dl_open (dl-open.c:883)
==23097==    by 0x51416BB: dlopen_doit (dlopen.c:56)
==23097==    by 0x5225C27: _dl_catch_exception (dl-error-skeleton.c:208)
==23097==    by 0x5225CF2: _dl_catch_error (dl-error-skeleton.c:227)
==23097==    by 0x51411AD: _dlerror_run (dlerror.c:138)
==23097==    by 0x5141747: dlopen_implementation (dlopen.c:71)
==23097==    by 0x5141747: dlopen@@GLIBC_2.34 (dlopen.c:81)
==23097==    by 0x4A36446: TROOT::InitInterpreter() (in /.../root_v6.26.04/lib/libCore.so.6.26.04)
==23097==    by 0x4A3660E: ROOT::Internal::GetROOT2() (in /.../root_v6.26.04/lib/libCore.so.6.26.04)
==23097==    by 0x4A4388C: TApplication::TApplication(char const*, int*, char**, void*, int) (in /.../root_v6.26.04/lib/libCore.so.6.26.04)
==23097==    by 0x486F45F: TRint::TRint(char const*, int*, char**, void*, int, bool, bool) (in /.../root_v6.26.04/lib/libRint.so.6.26.04)
==23097==    by 0x1092E6: main (in /.../root_v6.26.04/bin/root.exe)
==23097==  Address 0x54f9761 is 17 bytes inside a block of size 23 alloc'd
==23097==    at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==23097==    by 0x40271FF: malloc (rtld-malloc.h:56)
==23097==    by 0x40271FF: strdup (strdup.c:42)
==23097==    by 0x4008594: decompose_rpath (dl-load.c:629)
==23097==    by 0x400ABF5: cache_rpath (dl-load.c:696)
==23097==    by 0x400ABF5: cache_rpath (dl-load.c:677)
==23097==    by 0x400ABF5: _dl_map_object (dl-load.c:2165)
==23097==    by 0x4003494: openaux (dl-deps.c:64)
==23097==    by 0x5225C27: _dl_catch_exception (dl-error-skeleton.c:208)
==23097==    by 0x4003C7B: _dl_map_object_deps (dl-deps.c:248)
==23097==    by 0x400EA0E: dl_open_worker_begin (dl-open.c:592)
==23097==    by 0x5225C27: _dl_catch_exception (dl-error-skeleton.c:208)
==23097==    by 0x400DF99: dl_open_worker (dl-open.c:782)
==23097==    by 0x5225C27: _dl_catch_exception (dl-error-skeleton.c:208)
==23097==    by 0x400E34D: _dl_open (dl-open.c:883)
==23097==    by 0x51416BB: dlopen_doit (dlopen.c:56)
==23097==    by 0x5225C27: _dl_catch_exception (dl-error-skeleton.c:208)
==23097==    by 0x5225CF2: _dl_catch_error (dl-error-skeleton.c:227)
==23097==    by 0x51411AD: _dlerror_run (dlerror.c:138)
==23097==    by 0x5141747: dlopen_implementation (dlopen.c:71)
==23097==    by 0x5141747: dlopen@@GLIBC_2.34 (dlopen.c:81)
==23097==    by 0x4A36446: TROOT::InitInterpreter() (in /.../root_v6.26.04/lib/libCore.so.6.26.04)
==23097==    by 0x4A3660E: ROOT::Internal::GetROOT2() (in /.../root_v6.26.04/lib/libCore.so.6.26.04)
==23097==    by 0x4A4388C: TApplication::TApplication(char const*, int*, char**, void*, int) (in /.../root_v6.26.04/lib/libCore.so.6.26.04)
==23097==    by 0x486F45F: TRint::TRint(char const*, int*, char**, void*, int, bool, bool) (in /.../root_v6.26.04/lib/libRint.so.6.26.04)
==23097==    by 0x1092E6: main (in /.../root_v6.26.04/bin/root.exe)
==23097== 
==23097== Invalid read of size 8
==23097==    at 0x40286C8: strncmp (strcmp.S:172)
==23097==    by 0x400668D: is_dst (dl-load.c:216)
==23097==    by 0x4007F79: _dl_dst_substitute (dl-load.c:295)
==23097==    by 0x40082B7: fillin_rpath.isra.0 (dl-load.c:483)
==23097==    by 0x4008602: decompose_rpath (dl-load.c:654)
==23097==    by 0x400ABF5: cache_rpath (dl-load.c:696)
==23097==    by 0x400ABF5: cache_rpath (dl-load.c:677)
==23097==    by 0x400ABF5: _dl_map_object (dl-load.c:2165)
==23097==    by 0x4003494: openaux (dl-deps.c:64)
==23097==    by 0x5225C27: _dl_catch_exception (dl-error-skeleton.c:208)
==23097==    by 0x4003C7B: _dl_map_object_deps (dl-deps.c:248)
==23097==    by 0x400EA0E: dl_open_worker_begin (dl-open.c:592)
==23097==    by 0x5225C27: _dl_catch_exception (dl-error-skeleton.c:208)
==23097==    by 0x400DF99: dl_open_worker (dl-open.c:782)
==23097==    by 0x5225C27: _dl_catch_exception (dl-error-skeleton.c:208)
==23097==    by 0x400E34D: _dl_open (dl-open.c:883)
==23097==    by 0x51416BB: dlopen_doit (dlopen.c:56)
==23097==    by 0x5225C27: _dl_catch_exception (dl-error-skeleton.c:208)
==23097==    by 0x5225CF2: _dl_catch_error (dl-error-skeleton.c:227)
==23097==    by 0x51411AD: _dlerror_run (dlerror.c:138)
==23097==    by 0x5141747: dlopen_implementation (dlopen.c:71)
==23097==    by 0x5141747: dlopen@@GLIBC_2.34 (dlopen.c:81)
==23097==    by 0x4A36446: TROOT::InitInterpreter() (in /.../root_v6.26.04/lib/libCore.so.6.26.04)
==23097==    by 0x4A3660E: ROOT::Internal::GetROOT2() (in /.../root_v6.26.04/lib/libCore.so.6.26.04)
==23097==    by 0x4A4388C: TApplication::TApplication(char const*, int*, char**, void*, int) (in /.../root_v6.26.04/lib/libCore.so.6.26.04)
==23097==    by 0x486F45F: TRint::TRint(char const*, int*, char**, void*, int, bool, bool) (in /.../root_v6.26.04/lib/libRint.so.6.26.04)
==23097==    by 0x1092E6: main (in /.../root_v6.26.04/bin/root.exe)
==23097==  Address 0x54f9761 is 17 bytes inside a block of size 23 alloc'd
==23097==    at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==23097==    by 0x40271FF: malloc (rtld-malloc.h:56)
==23097==    by 0x40271FF: strdup (strdup.c:42)
==23097==    by 0x4008594: decompose_rpath (dl-load.c:629)
==23097==    by 0x400ABF5: cache_rpath (dl-load.c:696)
==23097==    by 0x400ABF5: cache_rpath (dl-load.c:677)
==23097==    by 0x400ABF5: _dl_map_object (dl-load.c:2165)
==23097==    by 0x4003494: openaux (dl-deps.c:64)
==23097==    by 0x5225C27: _dl_catch_exception (dl-error-skeleton.c:208)
==23097==    by 0x4003C7B: _dl_map_object_deps (dl-deps.c:248)
==23097==    by 0x400EA0E: dl_open_worker_begin (dl-open.c:592)
==23097==    by 0x5225C27: _dl_catch_exception (dl-error-skeleton.c:208)
==23097==    by 0x400DF99: dl_open_worker (dl-open.c:782)
==23097==    by 0x5225C27: _dl_catch_exception (dl-error-skeleton.c:208)
==23097==    by 0x400E34D: _dl_open (dl-open.c:883)
==23097==    by 0x51416BB: dlopen_doit (dlopen.c:56)
==23097==    by 0x5225C27: _dl_catch_exception (dl-error-skeleton.c:208)
==23097==    by 0x5225CF2: _dl_catch_error (dl-error-skeleton.c:227)
==23097==    by 0x51411AD: _dlerror_run (dlerror.c:138)
==23097==    by 0x5141747: dlopen_implementation (dlopen.c:71)
==23097==    by 0x5141747: dlopen@@GLIBC_2.34 (dlopen.c:81)
==23097==    by 0x4A36446: TROOT::InitInterpreter() (in /.../root_v6.26.04/lib/libCore.so.6.26.04)
==23097==    by 0x4A3660E: ROOT::Internal::GetROOT2() (in /.../root_v6.26.04/lib/libCore.so.6.26.04)
==23097==    by 0x4A4388C: TApplication::TApplication(char const*, int*, char**, void*, int) (in /.../root_v6.26.04/lib/libCore.so.6.26.04)
==23097==    by 0x486F45F: TRint::TRint(char const*, int*, char**, void*, int, bool, bool) (in /.../root_v6.26.04/lib/libRint.so.6.26.04)
==23097==    by 0x1092E6: main (in /.../root_v6.26.04/bin/root.exe)
==23097== 

==23097== 
==23097== HEAP SUMMARY:
==23097==     in use at exit: 40,465,757 bytes in 14,492 blocks
==23097==   total heap usage: 136,771 allocs, 122,279 frees, 153,357,195 bytes allocated
==23097== 
==23097== LEAK SUMMARY:
==23097==    definitely lost: 0 bytes in 0 blocks
==23097==    indirectly lost: 0 bytes in 0 blocks
==23097==      possibly lost: 220,804 bytes in 174 blocks
==23097==    still reachable: 522,472 bytes in 4,139 blocks
==23097==                       of which reachable via heuristic:
==23097==                         multipleinheritance: 18,136 bytes in 8 blocks
==23097==         suppressed: 39,722,481 bytes in 10,179 blocks
==23097== Rerun with --leak-check=full to see details of leaked memory
==23097== 
==23097== For lists of detected and suppressed errors, rerun with: -s
==23097== ERROR SUMMARY: 4 errors from 2 contexts (suppressed: 184 from 43)

Could you post the report from valgrind? (I need to see the backtrace - it sounds as if your libc does things that vagrind doesn’t like)

Backtrace added.

Thank you very much for all your replies.

When I run the following command:
valgrind --suppressions=/etc/root/valgrind-root.supp /usr/bin/root.exe -q -l

The output I get :

HEAP SUMMARY:
    in use at exit: 24,302,753 bytes in 30,311 blocks
    total heap usage: 95,833 allocs, 65,522 frees, 60,383,494 bytes allocated
LEAK SUMMARY:
    definitely lost: 16 bytes in 1 blocks
    indirectly lost: 32 bytes in 1 blocks
    possibly lost: 23,815,191 bytes in 26,189 blocks
    still reachable: 476,983 bytes in 3,978 blocks
        of which reachable via heuristic:
                stdstring          : 40 bytes in 1 blocks
                 multipleinheritance: 17,856 bytes in 8 blocks
  suppressed: 10,531 bytes in 142 blocks
 ERROR SUMMARY: 115 errors from 43 contexts (suppressed: 0 from 0)

Here is the total backtrace:
erreur valgrind.txt (49.6 KB)

Now, when I run this command :

valgrind --suppressions=$(root-config --etcdir)/valgrind-root.supp $(root-config --bindir)/root.exe -q -l

I get this backtrace:

$ valgrind --suppressions=$(root-config --etcdir)/valgrind-root.supp $(root-config --bindir)/root.exe -q -l

==2085== Memcheck, a memory error detector

==2085== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.

==2085== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info

==2085== Command: /usr/bin/root.exe -q -l

==2085== 



==2085== 

==2085== HEAP SUMMARY:

==2085==     in use at exit: 24,302,753 bytes in 30,311 blocks

==2085==   total heap usage: 95,846 allocs, 65,535 frees, 60,384,096 bytes allocated

==2085== 

==2085== LEAK SUMMARY:

==2085==    definitely lost: 16 bytes in 1 blocks

==2085==    indirectly lost: 32 bytes in 1 blocks

==2085==      possibly lost: 9,821,877 bytes in 7,967 blocks

==2085==    still reachable: 476,983 bytes in 3,978 blocks

==2085==                       of which reachable via heuristic:

==2085==                         stdstring          : 40 bytes in 1 blocks

==2085==                         multipleinheritance: 17,856 bytes in 8 blocks

==2085==         suppressed: 14,003,845 bytes in 18,364 blocks

==2085== Rerun with --leak-check=full to see details of leaked memory

==2085== 

==2085== For counts of detected and suppressed errors, rerun with: -v

==2085== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 115 from 43)

With no error displayed in the terminal this time …

@CorentinH Only 115 errors? You are really lucky.
ROOT 6.20/08 on Centos 7 / x86_64 / GCC 4.8.5 gives me (no “lost” bytes):
==24913== ERROR SUMMARY: 10569 errors from 5 contexts (suppressed: 112 from 43)

Well, your two backtrace outputs suggest that you have two ROOT versions “mixed”.
Check:
root-config --version
root-config --bindir # /usr/bin
root-config --libdir # /usr/lib
root-config --etcdir # /etc/root

@Wile_E_Coyote

$ root-config --version
6.20/04

$ root-config --libdir
/usr/lib

$ root-config --etcdir
/usr/etc

$ root-config --bindir
/usr/bin

So, where does “/etc/root” come from?
Try:
dpkg -S /etc/root/valgrind-root.supp

$ dpkg -S /etc/root/valgrind-root.supp
root-lpc: /etc/root/valgrind-root.supp

Well, that really means that your system is screwed.
First, make sure that you “completely remove” / “purge” (i.e. “remove with any associated configuration files”) all ROOT related packages (e.g., dpkg --list "*root*lpc*"; sudo apt-get purge "*root*lpc*").
Then, delete your current ROOT binaries and build it from scratch again.

Oh well, I see … A cleaning is in order then !

For information, with the correct valgrind-root.supp file :

$ valgrind --suppressions=/usr/etc/valgrind-root.supp ./run
 Memcheck, a memory error detector
Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
 Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
 Command: ./2read

HEAP SUMMARY:
  in use at exit: 31,864,446 bytes in 47,714 blocks
  total heap usage: 146,196 allocs, 98,482 frees, 108,158,696 bytes allocated
LEAK SUMMARY:
 definitely lost: 16 bytes in 1 blocks
 indirectly lost: 32 bytes in 1 blocks
 possibly lost: 10,777,804 bytes in 8,686 blocks
 still reachable: 1,834,862 bytes in 15,447 blocks
                     of which reachable via heuristic:
                       stdstring          : 40 bytes in 1 blocks
                       newarray           : 16,640 bytes in 30 blocks
                       multipleinheritance: 14,688 bytes in 2 blocks
  suppressed: 19,251,732 bytes in 23,579 blocks
Rerun with --leak-check=full to see details of leaked memory

 For counts of detected and suppressed errors, rerun with: -v
 ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2048 from 183)

And the output of the command leak-check=full:
leak-check-full.txt (993.8 KB)

Well, I would do the following:

sudo apt-get purge "*root*lpc*" # remove any ROOT system package
dpkg --list "*root*lpc*" # make sure all are gone
cd /currently/installed/root/build/subdirectory
sudo xargs rm < install_manifest.txt # remove own ROOT binaries

Then, remove the source and build subdirectories to start everything from scratch.
Finally, download and build the new version (if possible, take the most recent available version).
See also: Sourcing root for all users

Last, but not least … note that the ROOT Team provides ready-to-use binary distributions for “Ubuntu 18 / gcc 7.5”, which you just need to download and unpack (see “Download a pre-compiled binary distribution”).

Thank you so much for your help !

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