Segfault when drawing canvas stored in file


Please read tips for efficient and successful posting and posting code

Describe the bug

Segmentation fault while attempting to draw any canvas stored in the file. Stack trace is however different for various canvases:

  1. Drawing empty default canvas from file

   #8  0x00007b1d6cfb963e in TGX11::SelectWindow(int) () from /opt/root/install/lib/libGX11.so
   #9  0x00007b1d58666ad2 in TPadPainter::SelectDrawable(int) () from /opt/root/install/lib/libGpad.so
   #10 0x00007b1d5863bdd9 in TPad::cd(int) () from /opt/root/install/lib/libGpad.so
   #11 0x00007b1d5861af8a in TCanvas::cd(int) () from /opt/root/install/lib/libGpad.so
   #12 0x00007b1d5861322e in TCanvas::Resize(char const\*) () from /opt/root/install/lib/libGpad.so
   #13 0x00007b1d56b91acc in TRootCanvas::HandleContainerConfigure(Event_t\*) () from /opt/root/install/lib/libGui.so
   #14 0x00007b1d56a777cb in TGFrame::HandleEvent(Event_t\*) () from /opt/root/install/lib/libGui.so
   #15 0x00007b1d56a1521d in TGClient::HandleEvent(Event_t\*) () from /opt/root/install/lib/libGui.so
   #16 0x00007b1d56a15845 in TGClient::ProcessOneEvent() () from /opt/root/install/lib/libGui.so
   #17 0x00007b1d56a1589a in TGClient::HandleInput() () from /opt/root/install/lib/libGui.so
   #18 0x00007b1d77b4a848 in TUnixSystem::DispatchOneEvent(bool) () from /opt/root/install/lib/libCore.so
   #19 0x00007b1d77a33964 in TSystem::Run() () from /opt/root/install/lib/libCore.so
   #20 0x00007b1d779b5b97 in TApplication::Run(bool) () from /opt/root/install/lib/libCore.so
   #21 0x00007b1d77ea8d8f in TRint::Run(bool) () from /opt/root/install/lib/libRint.so
   #22 0x0000566ab8fbb303 in main ()
  1. More complex canvas (TH1, multiple TF1)

   #8  0x0000707a489dcb2f in TGX11::CopyPixmapW(unsigned long, int, int, int) () from /opt/root/install/lib/libGX11.so
   #9  0x0000707a34d8dc90 in TPad::CopyPixmap() () from /opt/root/install/lib/libGpad.so
   #10 0x0000707a34d6a060 in TCanvas::Flush() () from /opt/root/install/lib/libGpad.so
   #11 0x0000707a333922e8 in TRootCanvas::HandleContainerExpose(Event_t\*) () from /opt/root/install/lib/libGui.so
   #12 0x0000707a33277717 in TGFrame::HandleEvent(Event_t\*) () from /opt/root/install/lib/libGui.so
   #13 0x0000707a3321521d in TGClient::HandleEvent(Event_t\*) () from /opt/root/install/lib/libGui.so
   #14 0x0000707a33215845 in TGClient::ProcessOneEvent() () from /opt/root/install/lib/libGui.so
   #15 0x0000707a3321589a in TGClient::HandleInput() () from /opt/root/install/lib/libGui.so
   #16 0x0000707a5434a848 in TUnixSystem::DispatchOneEvent(bool) () from /opt/root/install/lib/libCore.so
   #17 0x0000707a54233964 in TSystem::Run() () from /opt/root/install/lib/libCore.so
   #18 0x0000707a541b5b97 in TApplication::Run(bool) () from /opt/root/install/lib/libCore.so
   #19 0x0000707a545e6d8f in TRint::Run(bool) () from /opt/root/install/lib/libRint.so
   #20 0x000063791e5e5303 in main ()

Expected behavior

Visualization of a stunning canvas!

To Reproduce (GPT generated example)

 #include <TApplication.h> 
 #include <TCanvas.h> 
 #include <TFile.h> 
 #include <TF1.h> 
 #include <TH1D.h> 
 #include <TRandom3.h> 
 #include 
 #include 
 namespace 
 { 
 int WriteSmokeFile(const std::string &file_name) 
 { 
 int argc = 0; 
 TApplication app("root_canvas_smoke_test_write", &argc, nullptr); 
 TFile output(file_name.c_str(), "RECREATE"); 
 if (output.IsZombie()) 
 { 
 std::cerr << "Could not create " << file_name << "\n"; 
 return 1; 
 } 
 TRandom3 rng(12345); 
 auto hist = new TH1D("h_gaus", "Plain Gaussian;X;Counts", 100, -5.0, 5.0); 
 for (int i = 0; i < 10000; ++i) 
 { 
 hist->Fill(rng.Gaus(0.0, 1.0)); 
 } 
 auto canvas_hist = new TCanvas("canvas_hist", "Plain histogram canvas", 800, 600); 
 hist->Draw("HIST"); 
 canvas_hist->Write(); 
 auto fit = new TF1("gaus_fit", "gaus", -5.0, 5.0); 
 hist->Fit(fit, "Q"); 
 auto canvas_fit = new TCanvas("canvas_fit", "Histogram with fit canvas", 800, 600); 
 hist->Draw("E"); 
 fit->Draw("SAME"); 
 canvas_fit->Write(); 
 output.cd(); 
 hist->Write("standalone_histogram"); 
 fit->Write("standalone_fit"); 
 output.Close(); 
 std::cout << "Wrote " << file_name << "\n"; 
 return 0; 
 } 
 int ReadSmokeCanvas(const std::string &file_name, const std::string &canvas_name) 
 { 
 int argc = 0; 
 TApplication app("root_canvas_smoke_test_read", &argc, nullptr); 
 TFile input(file_name.c_str(), "READ"); 
 if (input.IsZombie()) 
 { 
 std::cerr << "Could not open " << file_name << "\n"; 
 return 1; 
 } 
 auto *canvas = dynamic_cast<TCanvas *>(input.Get(canvas_name.c_str())); 
 if (!canvas) 
 { 
 std::cerr << "Could not find TCanvas " << canvas_name << " in " << file_name << "\n"; 
 input.ls(); 
 return 1; 
 } 
 canvas->Draw(); 
 canvas->Modified(); 
 canvas->Update(); 
 std::cout << "Opened " << canvas_name << " from " << file_name << ". Close the ROOT window to exit.\n"; 
 app.Run(); 
 return 0; 
 } 
 } // namespace 
 int main(int argc, char **argv) 
 { 
 const std::string mode = argc > 1 ? argv[1] : "write"; 
 const std::string file_name = argc > 2 ? argv[2] : "root_canvas_smoke_test.root"; 
 const std::string canvas_name = argc > 3 ? argv[3] : "canvas_fit"; 
 if (mode == "write") 
 { 
 return WriteSmokeFile(file_name); 
 } 
 if (mode == "read") 
 { 
 return ReadSmokeCanvas(file_name, canvas_name); 
 } 
 std::cerr << "Usage:\n" 
 << "  root_canvas_smoke_test write [file.root]\n" 
 << "  root_canvas_smoke_test read [file.root] [canvas_name]\n"; 
 return 1; 
 } 

Setup

ROOT v6.40.02
Built for linuxx8664gcc on Jul 15 2026, 21:27:32
From tags/6-40-02@6-40-02
With c++ (Ubuntu 15.2.0-16ubuntu1) 15.2.0 std202002
Binary directory: /opt/root/install/bin

ROOT build from source

Additional context

After updating from previous version built 2 months ago, I am no longer able to draw canvases that were ok before.

I see the same on mac.

% root
   ------------------------------------------------------------------
  | Welcome to ROOT 6.41.01                        https://root.cern |
  | (c) 1995-2025, The ROOT Team; conception: R. Brun, F. Rademakers |
  | Built for macosxarm64 on Jul 16 2026, 07:24:50                   |
  | From heads/master@v6-39-99-881-gda08f465233                      |
  | With Apple clang version 21.0.0 (clang-2100.1.1.101) std201703   |
  | Try '.help'/'.?', '.demo', '.license', '.credits', '.quit'/'.q'  |
   ------------------------------------------------------------------

root [0] TFile *hpx = TFile::Open("hpx.root")
(TFile *) 0xb35c60e00
root [1] hpx->ls()
TFile**		hpx.root	
 TFile*		hpx.root	
  KEY: TCanvas	c1;1	c1
root [2] c1->Draw();

 *** Break *** segmentation violation
[/usr/lib/system/libsystem_platform.dylib] _sigtramp (no debug info)
[/Users/couet/git/couet-root-bin/lib/libGpad.so] TCanvas::Build() (no debug info)
[/Users/couet/git/couet-root-bin/lib/libGpad.so] TCanvas::Draw(char const*) (no debug info)
[/Users/couet/git/couet-root-bin/lib/libCling.so] cling::IncrementalExecutor::executeWrapper(llvm::StringRef, cling::Value*) const (no debug info)
[/Users/couet/git/couet-root-bin/lib/libCling.so] cling::Interpreter::RunFunction(clang::FunctionDecl const*, cling::Value*) (no debug info)
[/Users/couet/git/couet-root-bin/lib/libCling.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/couet/git/couet-root-bin/lib/libCling.so] cling::Interpreter::process(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&, cling::Value*, cling::Transaction**, bool) (no debug info)
[/Users/couet/git/couet-root-bin/lib/libCling.so] cling::MetaProcessor::process(llvm::StringRef, cling::Interpreter::CompilationResult&, cling::Value*, bool) (no debug info)
[/Users/couet/git/couet-root-bin/lib/libCling.so] HandleInterpreterException(cling::MetaProcessor*, char const*, cling::Interpreter::CompilationResult&, cling::Value*) (no debug info)
[/Users/couet/git/couet-root-bin/lib/libCling.so] TCling::ProcessLine(char const*, TInterpreter::EErrorCode*) (no debug info)
[/Users/couet/git/couet-root-bin/lib/libRint.so] TRint::ProcessLineNr(char const*, char const*, int*) (no debug info)
[/Users/couet/git/couet-root-bin/lib/libRint.so] TRint::HandleTermInput() (no debug info)
[/Users/couet/git/couet-root-bin/lib/libCore.so] TUnixSystem::CheckDescriptors() (no debug info)
[/Users/couet/git/couet-root-bin/lib/libCore.so] TMacOSXSystem::DispatchOneEvent(bool) (no debug info)
[/Users/couet/git/couet-root-bin/lib/libCore.so] TSystem::InnerLoop() (no debug info)
[/Users/couet/git/couet-root-bin/lib/libCore.so] TSystem::Run() (no debug info)
[/Users/couet/git/couet-root-bin/lib/libCore.so] TApplication::Run(bool) (no debug info)
[/Users/couet/git/couet-root-bin/lib/libRint.so] TRint::Run(bool) (no debug info)
[/Users/couet/git/couet-root-bin/bin/root.exe] main (no debug info)
[/usr/lib/dyld] start (no debug info)
Root > 

May be @linev can help with that ? I’ll try to look myself.

The drawing is the problem. Accessing the canvas via an other method is working:

root [0] TFile *hpx = TFile::Open("hpx.root")
(TFile *) 0xafaa44700
root [1] c1->ls();
Canvas Name=c1 Title=c1 Option=
 TCanvas fXlowNDC=0 fYlowNDC=0 fWNDC=1 fHNDC=1 Name= c1 Title= c1 Option=
  OBJ: TList	TList	Doubly linked list : 0
   TFrame  X1= -4.000000 Y1=0.000000 X2=4.000000 Y2=851.550000
   OBJ: TH1F	hpx	This is the px distribution : 1 at: 0xafa9fb400
   OBJ: TPaveText	title  	X1= -2.191691 Y1=890.822153 X2=2.191691 Y2=952.671575
root [2] 

Even putting the canvas in memory and Drawing it afterwards does not work:

% root
   ------------------------------------------------------------------
  | Welcome to ROOT 6.41.01                        https://root.cern |
  | (c) 1995-2025, The ROOT Team; conception: R. Brun, F. Rademakers |
  | Built for macosxarm64 on Jul 16 2026, 07:24:50                   |
  | From heads/master@v6-39-99-881-gda08f465233                      |
  | With Apple clang version 21.0.0 (clang-2100.1.1.101) std201703   |
  | Try '.help'/'.?', '.demo', '.license', '.credits', '.quit'/'.q'  |
   ------------------------------------------------------------------

root [0] TFile *hpx = TFile::Open("hpx.root")
(TFile *) 0x85c7cc700
root [1] TCanvas *c = (TCanvas *)hpx->Get("c1");
root [2] c->Draw()

 *** Break *** segmentation violation
[/usr/lib/system/libsystem_platform.dylib] _sigtramp (no debug info)
[/Users/couet/git/couet-root-bin/lib/libGpad.so] TCanvas::Build() (no debug info)
[/Users/couet/git/couet-root-bin/lib/libGpad.so] TCanvas::Draw(char const*) (no debug info)
[/Users/couet/git/couet-root-bin/lib/libCling.so] cling::IncrementalExecutor::executeWrapper(llvm::StringRef, cling::Value*) const (no debug info)
[/Users/couet/git/couet-root-bin/lib/libCling.so] cling::Interpreter::RunFunction(clang::FunctionDecl const*, cling::Value*) (no debug info)
[/Users/couet/git/couet-root-bin/lib/libCling.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/couet/git/couet-root-bin/lib/libCling.so] cling::Interpreter::process(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&, cling::Value*, cling::Transaction**, bool) (no debug info)
[/Users/couet/git/couet-root-bin/lib/libCling.so] cling::MetaProcessor::process(llvm::StringRef, cling::Interpreter::CompilationResult&, cling::Value*, bool) (no debug info)
[/Users/couet/git/couet-root-bin/lib/libCling.so] HandleInterpreterException(cling::MetaProcessor*, char const*, cling::Interpreter::CompilationResult&, cling::Value*) (no debug info)
[/Users/couet/git/couet-root-bin/lib/libCling.so] TCling::ProcessLine(char const*, TInterpreter::EErrorCode*) (no debug info)
[/Users/couet/git/couet-root-bin/lib/libRint.so] TRint::ProcessLineNr(char const*, char const*, int*) (no debug info)
[/Users/couet/git/couet-root-bin/lib/libRint.so] TRint::HandleTermInput() (no debug info)
[/Users/couet/git/couet-root-bin/lib/libCore.so] TUnixSystem::CheckDescriptors() (no debug info)
[/Users/couet/git/couet-root-bin/lib/libCore.so] TMacOSXSystem::DispatchOneEvent(bool) (no debug info)
[/Users/couet/git/couet-root-bin/lib/libCore.so] TSystem::InnerLoop() (no debug info)
[/Users/couet/git/couet-root-bin/lib/libCore.so] TSystem::Run() (no debug info)
[/Users/couet/git/couet-root-bin/lib/libCore.so] TApplication::Run(bool) (no debug info)
[/Users/couet/git/couet-root-bin/lib/libRint.so] TRint::Run(bool) (no debug info)
[/Users/couet/git/couet-root-bin/bin/root.exe] main (no debug info)
[/usr/lib/dyld] start (no debug info)
Root > 

Printing is fine:

root [0] TFile *hpx = TFile::Open("hpx.root")
(TFile *) 0xad0324380
root [1] c1->Print("c1.pdf")
Info in <TCanvas::Print>: pdf file c1.pdf has been created
root [2] 

The file c1.pdf is correct.

Ok I thought I was loosing my mind, doing some silly mistake…

I also found that when created with interpreter:

auto c = new TCanvas();
auto f = new TFile();
f->cd();
c->Write();
f->Close();

the (empty) canvas is drawn but only if Paint() is called first, e.i:

TFile *_file0 = TFile::Open(ā€œf.rootā€)

c1->Paint()
c1->Draw()

Without calling Paint() first, seg fault occurs.

I found a fix and made a PR: Add a protection against undefined fPainter by couet Ā· Pull Request #22832 Ā· root-project/root Ā· GitHub

But this PR needs to be checked by @linev before merging it.
If you build ROOT yourself you can test it.

Thanks for reporting this issue.

Works like charm, many thanks for the fast fix!