Accessing parameter from a context menu function results in segmentation violation


ROOT Version: 6.26.10
Platform: Ubuntu 22.04
Compiler: g++ 11.3.0


I’m trying to add a context menu function to a class derived from TLine, using the // *MENU* comment. The function does show up when opening the context menu, but the moment the function accesses the single parameter read from the dialog I get a segmentation violation. I wrote a simple class to re-create this issue consisting of a header testLine.h

#pragma once

#include <iostream>
#include <string>

#include "TLine.h"

class testLine : public TLine
{
public:
   testLine() {}
   ~testLine() {}

   void MenuFunction(const double& lineWidth) { std::cout<<__PRETTY_FUNCTION__<<std::endl; std::cout<<"line width "<<lineWidth<<std::endl; SetLineWidth(lineWidth); } // *MENU*

   void Label(const std::string& label) { fLabel = label; }

   using TLine::Draw;
   void Draw(const double& x, const double& y) { SetX1(x); SetX2(x+y); SetY1(y); SetY2(y-x); TLine::Draw(); }

private:
   std::string fLabel{""};

   ClassDef(testLine, 1);
};

and an almost empty source file testLine.cxx

#include "testLine.h"

ClassImp(testLine)

I compile the class using the commands

rootcling -f testLineDict.cxx testLine.h LinkDef.h -I. -rml libtestLine.so -rmf testLine.rootmap
g++ -fPIC -c testLineDict.cxx -o testLineDict.o `root-config --cflags`
g++ -fPIC -c testLine.cxx -o testLine.o `root-config --cflags`
g++ -shared -o libtestLine.so testLine.o testLineDict.o

and run the macro lineTest.C

void lineTest()
{
	auto c1 = new TCanvas;

	std::cout<<"created canvas c1 "<<c1<<std::endl;

	auto a = new testLine;
	a->Label("test a");
	a->Draw(0.1, 0.15);
	a->Print();

	c1->GetListOfPrimitives()->Print();
}

which gives me this output:

root [0] 
Processing lineTest.C...
created canvas c1 0x5574f7756da0
testLine  X1=0.100000 Y1=0.150000 X2=0.250000 Y2=0.050000
Collection name='TList', class='TList', size=1
 testLine  X1=0.100000 Y1=0.150000 X2=0.250000 Y2=0.050000
root [1] void testLine::MenuFunction(const double &)

 *** Break *** segmentation violation
line width 


===========================================================
There was a crash.
This is the entire stack trace of all threads:
===========================================================
#0  0x00007f82fbd6945a in __GI___wait4 (pid=1955243, stat_loc=stat_loc
entry=0x7ffec7c84418, options=options
entry=0, usage=usage
entry=0x0) at ../sysdeps/unix/sysv/linux/wait4.c:30
#1  0x00007f82fbd6941b in __GI___waitpid (pid=<optimized out>, stat_loc=stat_loc
entry=0x7ffec7c84418, options=options
entry=0) at ./posix/waitpid.c:38
#2  0x00007f82fbccfbcb in do_system (line=<optimized out>) at ../sysdeps/posix/system.c:171
#3  0x00007f82fc4098a4 in TUnixSystem::StackTrace() () from /opt/cern/root/root_v6.26.10/lib/libCore.so.6.26
#4  0x00007f82fc406bb5 in TUnixSystem::DispatchSignals(ESignals) () from /opt/cern/root/root_v6.26.10/lib/libCore.so.6.26
#5  <signal handler called>
#6  0x00007f82df84607d in ?? ()
#7  0x0000000000000004 in ?? ()
#8  0x00007f82f7335a75 in unsigned long long (anonymous namespace)::sv_to<unsigned long long>(cling::Value const&) () from /opt/cern/root/root_v6.26.10/lib/libCling.so
#9  0x00007f82f733c1b8 in TClingCallFunc::exec(void*, void*) () from /opt/cern/root/root_v6.26.10/lib/libCling.so
#10 0x00007f82f72e084a in TCling::Execute(TObject*, TClass*, char const*, char const*, bool, int*) () from /opt/cern/root/root_v6.26.10/lib/libCling.so
#11 0x00007f82f72e0b82 in TCling::Execute(TObject*, TClass*, char const*, char const*, int*) () from /opt/cern/root/root_v6.26.10/lib/libCling.so
#12 0x00007f82fc2e0d3a in TObject::Execute(char const*, char const*, int*) () from /opt/cern/root/root_v6.26.10/lib/libCore.so.6.26
#13 0x00007f82fc3ecf28 in TContextMenu::Execute(TObject*, TFunction*, char const*) () from /opt/cern/root/root_v6.26.10/lib/libCore.so.6.26
#14 0x00007f82e00e2506 in TRootContextMenu::ProcessMessage(long, long, long) () from /opt/cern/root/root_v6.26.10/lib/libGui.so.6.26.10
#15 0x00007f82dffe793d in TGFrame::HandleClientMessage(Event_t*) () from /opt/cern/root/root_v6.26.10/lib/libGui.so.6.26.10
#16 0x00007f82dfff8cd0 in TGFrame::HandleEvent(Event_t*) () from /opt/cern/root/root_v6.26.10/lib/libGui.so.6.26.10
#17 0x00007f82dffa0f0d in TGClient::HandleMaskEvent(Event_t*, unsigned long) () from /opt/cern/root/root_v6.26.10/lib/libGui.so.6.26.10
#18 0x00007f82dffa10af in TGClient::ProcessOneEvent() () from /opt/cern/root/root_v6.26.10/lib/libGui.so.6.26.10
#19 0x00007f82dffa118b in TGClient::HandleInput() () from /opt/cern/root/root_v6.26.10/lib/libGui.so.6.26.10
#20 0x00007f82fc4073e8 in TUnixSystem::DispatchOneEvent(bool) () from /opt/cern/root/root_v6.26.10/lib/libCore.so.6.26
#21 0x00007f82fc3115b2 in TSystem::ProcessEvents() () from /opt/cern/root/root_v6.26.10/lib/libCore.so.6.26
#22 0x00007f82dff9f3dd in TGClient::WaitFor(TGWindow*) () from /opt/cern/root/root_v6.26.10/lib/libGui.so.6.26.10
#23 0x00007f82e00e1510 in TRootContextMenu::Dialog(TObject*, TFunction*) () from /opt/cern/root/root_v6.26.10/lib/libGui.so.6.26.10
#24 0x00007f82fc3ebc18 in TContextMenu::Action(TObject*, TMethod*) () from /opt/cern/root/root_v6.26.10/lib/libCore.so.6.26
#25 0x00007f82e00e25a0 in TRootContextMenu::ProcessMessage(long, long, long) () from /opt/cern/root/root_v6.26.10/lib/libGui.so.6.26.10
#26 0x00007f82dffe793d in TGFrame::HandleClientMessage(Event_t*) () from /opt/cern/root/root_v6.26.10/lib/libGui.so.6.26.10
#27 0x00007f82dfff8cd0 in TGFrame::HandleEvent(Event_t*) () from /opt/cern/root/root_v6.26.10/lib/libGui.so.6.26.10
#28 0x00007f82dffa0ace in TGClient::HandleEvent(Event_t*) () from /opt/cern/root/root_v6.26.10/lib/libGui.so.6.26.10
#29 0x00007f82dffa112d in TGClient::ProcessOneEvent() () from /opt/cern/root/root_v6.26.10/lib/libGui.so.6.26.10
#30 0x00007f82dffa118b in TGClient::HandleInput() () from /opt/cern/root/root_v6.26.10/lib/libGui.so.6.26.10
#31 0x00007f82fc4073e8 in TUnixSystem::DispatchOneEvent(bool) () from /opt/cern/root/root_v6.26.10/lib/libCore.so.6.26
#32 0x00007f82fc311817 in TSystem::Run() () from /opt/cern/root/root_v6.26.10/lib/libCore.so.6.26
#33 0x00007f82fc2a7977 in TApplication::Run(bool) () from /opt/cern/root/root_v6.26.10/lib/libCore.so.6.26
#34 0x00007f82fc6cf38b in TRint::Run(bool) () from /opt/cern/root/root_v6.26.10/lib/libRint.so.6.26
#35 0x00005574f497d2f3 in main ()
===========================================================

I tried finding other issues discussing this problem, but I didn’t see anyone else having this problem. Any idea what I’m doing wrong here? Or is there somewhere all the possible comment flags are explained? I saw some of the root classes using *ARGS=... to set default values based on members of the class (I think?) and some using *GETTER=... to do something else (provide the corresponding getter function?), but what these flags exactly do I don’t know.

It seems to work for me:

% root           
   ------------------------------------------------------------------
  | Welcome to ROOT 6.29/01                        https://root.cern |
  | (c) 1995-2022, The ROOT Team; conception: R. Brun, F. Rademakers |
  | Built for macosx64 on Apr 25 2023, 07:20:18                      |
  | From heads/master@v6-29-01-1214-ge349236f38                      |
  | With Apple clang version 14.0.0 (clang-1400.0.29.202)            |
  | Try '.help'/'.?', '.demo', '.license', '.credits', '.quit'/'.q'  |
   ------------------------------------------------------------------

root [0] .L testline.h
root [1] auto a = new testLine;
root [2] a->Draw(0.1, 0.15);
Info in <TCanvas::MakeDefCanvas>:  created default TCanvas with name c1
root [3] 

then a ritgh click on the line gives:

Don’t pass the argument by reference (&). I.e. Use MenuFunction(const double lineWidth) instead of MenuFunction(const double& lineWidth):

void MenuFunction(const double lineWidth) { std::cout<<__PRETTY_FUNCTION__<<std::endl; std::cout<<"line width "<<lineWidth<<std::endl; SetLineWidth(lineWidth); } // *MENU*

This gives (on Windows, but it doesn’t matter):

root [1] auto a = new testLine;
root [2] a->Draw(0.1, 0.15);
Info in <TCanvas::MakeDefCanvas>:  created default TCanvas with name c1
root [3] void __thiscall testLine::MenuFunction(const double)
line width 3

Thank you, that was indeed the issue.

1 Like

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