Segmentation violation when plotting with Garfield++

Hello,

The behavior started occurring after I pulled commit 3adfd42 (“Merge branch ‘PlottingEngine’ into ‘master’”). I have already tried building Garfield++ from scratch, but not even the default examples will work, only the ones that do not use ROOT to plot the results (e.g. Examples/GasFile/printTable.C). The segmentation violation only happens at the end of the program, after clicking on “Quit ROOT” on one of the canvases.

 *** Break *** segmentation violation



===========================================================
There was a crash.
This is the entire stack trace of all threads:
===========================================================
#0  0x000070b9c92ea3ea in __GI___wait4 (pid=2871686, stat_loc=stat_loc
entry=0x7ffcd1c88c68, options=options
entry=0, usage=usage
entry=0x0) at ../sysdeps/unix/sysv/linux/wait4.c:30
#1  0x000070b9c92ea3ab in __GI___waitpid (pid=<optimized out>, stat_loc=stat_loc
entry=0x7ffcd1c88c68, options=options
entry=0) at ./posix/waitpid.c:38
#2  0x000070b9c9250bdb in do_system (line=<optimized out>) at ../sysdeps/posix/system.c:171
#3  0x000070b9c9b46d08 in TUnixSystem::StackTrace() () from /home/gabrielribcesario/miniconda3/envs/nnbar/lib/libCore.so.6.34
#4  0x000070b9c9b46606 in TUnixSystem::DispatchSignals(ESignals) () from /home/gabrielribcesario/miniconda3/envs/nnbar/lib/libCore.so.6.34
#5  <signal handler called>
#6  0x000060b2d8563f10 in ?? ()
#7  0x000070b9c9245a56 in __cxa_finalize (d=0x70b9ca36b000) at ./stdlib/cxa_finalize.c:83
#8  0x000070b9c9e98546 in __do_global_dtors_aux () from /home/gabrielribcesario/garfieldpp/install/lib/libGarfield.so.0.3
#9  0x00007ffcd1c8c280 in ?? ()
#10 0x000070b9cc7c924e in _dl_fini () at ./elf/dl-fini.c:142
===========================================================


The lines below might hint at the cause of the crash. If you see question
marks as part of the stack trace, try to recompile with debugging information
enabled and export CLING_DEBUG=1 environment variable before running.
You may get help by asking at the ROOT forum https://root.cern/forum
preferably using the command (.forum bug) in the ROOT prompt.
Only if you are really convinced it is a bug in ROOT then please submit a
report at https://root.cern/bugs or (preferably) using the command (.gh bug) in
the ROOT prompt. Please post the ENTIRE stack trace
from above as an attachment in addition to anything else
that might help us fixing this issue.
===========================================================
#6  0x000060b2d8563f10 in ?? ()
#7  0x000070b9c9245a56 in __cxa_finalize (d=0x70b9ca36b000) at ./stdlib/cxa_finalize.c:83
#8  0x000070b9c9e98546 in __do_global_dtors_aux () from /home/gabrielribcesario/garfieldpp/install/lib/libGarfield.so.0.3
#9  0x00007ffcd1c8c280 in ?? ()
#10 0x000070b9cc7c924e in _dl_fini () at ./elf/dl-fini.c:142
===========================================================

On an unrelated note, the linker warns of an unused variable rule for PlottingEngine when generating the Garfield++ dictionary. In line 10 of Include/Garfield/LinkDef.h:

#pragma link C++ global Garfield::PlottingEngine;

Shouldn’t the correct linking rule be “class” instead of “global” since Garfield::PlottingEngine is a class and not a global variable? Either way, editing the linking rule does not fix the segmentation violations.

Sincerely,
Gabriel

Hi @keithwm422,

Let me add @hschindl in the loop.

Cheers,

Dev

Hi @gabrielribcesario, thanks for spotting the bug with the linking rule!

Unfortunately I didn’t manage to reproduce the crash. Can you remind me what platform/compiler you are using?

Cheers,

H.

Hello,

I’ve been using GCC 14.3.0, which effectively fixed the TrackDegrade segmentation violations. I’ve been using Conda as a package manager as well as to be able to use the newer GCC versions on Ubuntu 22.04 and older platforms alike, so I’ll attach the environment.yml (wrapped in a .zip due to the forum’s restrictions on file extensions). If you have a Conda distribution installed then this should enable you, for the most part, to use the same environment as mine regardless of your platform.

environment.zip (3.1 KB)

Just a heads up: the environment.yml includes ROOT 6.34, so there might conflicts if you already are sourcing a ROOT distribution elsewhere (e.g. a binary distribution). It also includes other Garfield++ dependencies, such as GSL and CMake.

Hello,

I just tried running the same examples that use Garfield’s plotting classes (e.g. plotExtrap.C, Gem.C, etc.) in a Fedora42 environment, with Fedora’s ROOT package and GCC 15.2.1, as well as in a Ubuntu 24.04 environment, with pre-compiled ROOT 6.36.04 and GCC 13.3.0, and got the same segmentation violation in both cases.

This is unlikely, but perhaps you have a cached installation file preventing you from triggering the crash? Can you try building Garfield with brand new build and CMAKE_INSTALL_PREFIX directories if you haven’t already?

Hello @hschindl,

After compiling Garfield++ with debugging info and running the Gem.C example with gdb I got the following backtrace:

(gdb) backtrace
#0  0x00005555555e6f10 in ?? ()
#1  0x00007ffff57d620a in std::default_delete<TStyle>::operator() (this=<optimized out>, __ptr=<optimized out>)
    at /home/gabrielribcesario/miniconda3/envs/nnbar/lib/gcc/x86_64-conda-linux-gnu/14.3.0/include/c++/bits/unique_ptr.h:87
#2  std::unique_ptr<TStyle, std::default_delete<TStyle> >::~unique_ptr (this=0x7ffff7e8f748 <Garfield::PlottingEngine::m_style>, __in_chrg=<optimized out>)
    at /home/gabrielribcesario/miniconda3/envs/nnbar/lib/gcc/x86_64-conda-linux-gnu/14.3.0/include/c++/bits/unique_ptr.h:399
#3  0x00007ffff4a45a56 in __cxa_finalize (d=0x7ffff5a7e000) at ./stdlib/cxa_finalize.c:83
#4  0x00007ffff567c0c2 in __do_global_dtors_aux () from /home/gabrielribcesario/garfieldpp/install/lib/libGarfield.so.0.3
#5  0x00007ffffffe4b00 in ?? ()
#6  0x00007ffff7fc924e in _dl_fini () at ./elf/dl-fini.c:142

The crash seems to be triggered during/after the call to the destructor of the Garfield::PlottingEngine class, more specifically by the m_style member. According to the TStyle class reference:

The current style is pointed by gStyle. When calling myStyle->cd(), gStyle is set to myStyle.

Lines 89, 95 and 106 of PlottingEngine.cc:

m_style->cd();

So it seemed to me that these lines were causing both gStyle and the unique_ptr to point to the same memory address, triggering the crash during the program shutdown (the ROOT environment likely frees gStyle and PlottingEngine tries to free it again, or vice-versa). I tried commenting out lines 89, 95 and 106 and to my surprise that didn’t work. So I did the simple thing and cut out the middle man: I replaced every occurrence of “m_style” with “gStyle”, which effectively fixed all the crashes.

Okay, I can now confirm that this is exactly what is happening. The unique_ptr destructor is being called after the ROOT environment has already freed the memory address pointed by m_style. Here is the AddressSanitizer output:

==2410049==ERROR: AddressSanitizer: heap-use-after-free on address 0x51b000003f80 at pc 0x7d228dd7eb03 bp 0x7ffde90800a0 sp 0x7ffde9080098
READ of size 8 at 0x51b000003f80 thread T0
    #0 0x7d228dd7eb02 in std::default_delete<TStyle>::operator()(TStyle*) const /home/gabrielribcesario/miniconda3/envs/nnbar/lib/gcc/x86_64-conda-linux-gnu/14.3.0/include/c++/bits/unique_ptr.h:93
    #1 0x7d228dd7eb02 in std::unique_ptr<TStyle, std::default_delete<TStyle> >::~unique_ptr() /home/gabrielribcesario/miniconda3/envs/nnbar/lib/gcc/x86_64-conda-linux-gnu/14.3.0/include/c++/bits/unique_ptr.h:399
    #2 0x7d228cc45a55 in __cxa_finalize stdlib/cxa_finalize.c:83
    #3 0x7d228d91b0c1  (/home/gabrielribcesario/garfieldpp/install/lib/libGarfield.so.0.3+0x11b0c1)

0x51b000003f80 is located 0 bytes inside of 1552-byte region [0x51b000003f80,0x51b000004590)
freed by thread T0 here:
    #0 0x7d22908b2f87 in operator delete(void*) ../../../../libsanitizer/asan/asan_new_delete.cpp:152
    #1 0x7d228d484540 in TList::Delete(char const*) (/home/gabrielribcesario/miniconda3/envs/nnbar/lib/libCore.so.6.34+0x284540)

previously allocated by thread T0 here:
    #0 0x7d22908b2814 in operator new(unsigned long) ../../../../libsanitizer/asan/asan_new_delete.cpp:95
    #1 0x7d228d423ef9 in TStorage::ObjectAlloc(unsigned long) (/home/gabrielribcesario/miniconda3/envs/nnbar/lib/libCore.so.6.34+0x223ef9)

SUMMARY: AddressSanitizer: heap-use-after-free /home/gabrielribcesario/miniconda3/envs/nnbar/lib/gcc/x86_64-conda-linux-gnu/14.3.0/include/c++/bits/unique_ptr.h:93 in std::default_delete<TStyle>

Hi @gabrielribcesario, thanks a lot! I will get rid of the unique_ptr…

1 Like

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