SetDirectory triggers a seg fault


ROOT Version: 6.28/00 (conda install root -c conda-forge)
Platform: macOS Ventura 13.4
Compiler: Apple clang version 14.0.3 (clang-1403.0.22.14.1)


I have histograms in a ROOT file that was analyzed a few years ago without any problem. But when a new student tried to use it and the analysis macro, he found that the macro always crashes with a segmentation fault.

The code below is a minimum one to reproduce the issue.

void crash () {
  auto directory = gDirectory; // crashes
  //auto directory = gROOT; // OK
  TFile f("test.root");
  auto h = (TH1D*)f.Get("signal")->Clone("cloned");
  h->SetDirectory(directory);
  f.Close();
  std::cout << "File closed" << std::endl;
  delete h; // crashes here
  std::cout << "Cloned histogram has been deleted" << std::endl;
}

In the 2nd line, if I copy gDirectory to directory before opening the ROOT file, deleting the cloned object causes a segmentation fault. But if I copy gROOT to directory, it does not.

In my understanding, saving gDirectory before opening a TFile, namely before switching to another directory, has been a valid and standard step for many years.

What is the problem of my code?

You can download the file from the Dropbox link below.

The issue does not happen when I use another TFile that I created for a test. Therefore maybe the above file is broken.

root [0] .x crash.C
File closed

 *** Break *** segmentation violation
[/usr/lib/system/libsystem_platform.dylib] _sigtramp (no debug info)
[/Users/oxon/anaconda3/envs/lab309/lib/libCore.6.28.00.so] TList::AddLast(TObject*) (no debug info)
[<unknown binary>] (no debug info)
[/Users/oxon/anaconda3/envs/lab309/lib/libCling.6.28.00.so] cling::IncrementalExecutor::executeWrapper(llvm::StringRef, cling::Value*) const (no debug info)
[/Users/oxon/anaconda3/envs/lab309/lib/libCling.6.28.00.so] cling::Interpreter::RunFunction(clang::FunctionDecl const*, cling::Value*) (no debug info)
[/Users/oxon/anaconda3/envs/lab309/lib/libCling.6.28.00.so] cling::Interpreter::EvaluateInternal(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&, cling::CompilationOptions, cling::Value*, cling::Transaction**, unsigned long) (no debug info)
[/Users/oxon/anaconda3/envs/lab309/lib/libCling.6.28.00.so] cling::MetaSema::actOnxCommand(llvm::StringRef, llvm::StringRef, cling::Value*) (no debug info)
[/Users/oxon/anaconda3/envs/lab309/lib/libCling.6.28.00.so] cling::MetaParser::isXCommand(cling::MetaSema::ActionResult&, cling::Value*) (no debug info)
[/Users/oxon/anaconda3/envs/lab309/lib/libCling.6.28.00.so] cling::MetaParser::isCommand(cling::MetaSema::ActionResult&, cling::Value*) (no debug info)
[/Users/oxon/anaconda3/envs/lab309/lib/libCling.6.28.00.so] cling::MetaProcessor::process(llvm::StringRef, cling::Interpreter::CompilationResult&, cling::Value*, bool) (no debug info)
[/Users/oxon/anaconda3/envs/lab309/lib/libCling.6.28.00.so] HandleInterpreterException(cling::MetaProcessor*, char const*, cling::Interpreter::CompilationResult&, cling::Value*) (no debug info)
[/Users/oxon/anaconda3/envs/lab309/lib/libCling.6.28.00.so] TCling::ProcessLine(char const*, TInterpreter::EErrorCode*) (no debug info)
[/Users/oxon/anaconda3/envs/lab309/lib/libCling.6.28.00.so] TCling::ProcessLineSynch(char const*, TInterpreter::EErrorCode*) (no debug info)
[/Users/oxon/anaconda3/envs/lab309/lib/libCore.6.28.00.so] TApplication::ExecuteFile(char const*, int*, bool) (no debug info)
[/Users/oxon/anaconda3/envs/lab309/lib/libRint.6.28.00.so] TRint::ProcessLineNr(char const*, char const*, int*) (no debug info)
[/Users/oxon/anaconda3/envs/lab309/lib/libRint.6.28.00.so] TRint::HandleTermInput() (no debug info)
[/Users/oxon/anaconda3/envs/lab309/lib/libCore.6.28.00.so] TUnixSystem::CheckDescriptors() (no debug info)
[/Users/oxon/anaconda3/envs/lab309/lib/libCore.6.28.00.so] TMacOSXSystem::DispatchOneEvent(bool) (no debug info)
[/Users/oxon/anaconda3/envs/lab309/lib/libCore.6.28.00.so] TSystem::InnerLoop() (no debug info)
[/Users/oxon/anaconda3/envs/lab309/lib/libCore.6.28.00.so] TSystem::Run() (no debug info)
[/Users/oxon/anaconda3/envs/lab309/lib/libCore.6.28.00.so] TApplication::Run(bool) (no debug info)
[/Users/oxon/anaconda3/envs/lab309/lib/libRint.6.28.00.so] TRint::Run(bool) (no debug info)
[/Users/oxon/anaconda3/envs/lab309/bin/root.exe] main (no debug info)
[/usr/lib/dyld] start (no debug info)
Root > 

It also crashes with the following M1 Mac environment

ROOT Version: 6.26/06
Platform: macOS 13.4
Compiler: Apple clang version 14.0.3 (clang-1403.0.22.14.1) Target: arm64-apple-darwin22.5.0

but it does not on an Intel Mac with an a bit old ROOT.

ROOT Version: 6.22/02
Platform: macOS 10.15.7
Compiler: clang version 10.0.1 Target: x86_64-apple-darwin19.6.0

Is there any critical change in ROOT directories between 6.22 and 6.26?

I guess @pcanal can help you.

Changing auto with TDirectory* is a workaround.

  TDirectory* directory = gDirectory;
1 Like
TDirectory* directory = gDirectory;

is the right solution.
Doing

auto directory = gDirectory; // crashes

is the moral equivalent (not technically, lots of technical details involved) of:

TDirectory &directory = gDirectory;

and so when doing:

h->SetDirectory(directory);

is actually does the equivalent of

h->SetDirectory( &f );

in your example.

Thank you Philippe.

I found a similar explanation here.
https://root.cern.ch/doc/master/structROOT_1_1Internal_1_1TDirectoryAtomicAdapter.html

I was not aware that TDirectoryAtomicAdapter was introduced in 2020. The macro that had my issue was written by the student before the implementation of TDirectoryAtomicAdapter.

I will use TDirectory* or gROOT instead.

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