Segmentation fault when using custom classes ::Class() function

Yes, this is what I was looking for. So it does look like the initialization of the TClass for TMnemonic is starting as expected but is not completing correctly.

Alongside (in the same directory as) the shared library that contains the code for TMnemonic, do you have a file with a similar name and the suffix: _rdict.pcm?

There are a number of _rdict.pcm files, yes. But there isn’t a single file that corresponds to the library I’m loading as the library is several other libraries (with individual pcm files) linked together.

Also, I just noticed that the sub-library used for the base class has the same name as the one used for the class inheriting from it (and thus the two _rdict.pcm files have the same name even though they are in two different directories). Could this be the issue?

I will try and rename the libraries for the base classes.

Okay, so that was apparently not the issue. The files that I have for the program itself are:

lib:
GROOTDict_rdict.pcm	      libTCal.so	 libTGRSIProof.so      libTPeakFitting.so    TBetaDecayDict_rdict.pcm  TGRSIintDict_rdict.pcm	     TNucleusDict_rdict.pcm	   TSuppressedDict_rdict.pcm
libGROOT.so		      libTDataParser.so  libTGUI.so	       libTPulseAnalyzer.so  TBgoDict_rdict.pcm        TGRSIProofDict_rdict.pcm      TPeakFittingDict_rdict.pcm
libGRSI.so		      libTDetector.so	 libTHistogramming.so  libTRawFile.so	     TCalDict_rdict.pcm        TGUIDict_rdict.pcm	     TPulseAnalyzerDict_rdict.pcm
libMakeFragmentHistograms.so  libTFormat.so	 libTKinematics.so     libTReaction.so	     TDetectorDict_rdict.pcm   THistogrammingDict_rdict.pcm  TRawFileDict_rdict.pcm
libTBetaDecay.so	      libTGRSIFit.so	 libTLoops.so	       libTSRIM.so	     TFormatDict_rdict.pcm     TKinematicsDict_rdict.pcm     TReactionDict_rdict.pcm
libTBgo.so		      libTGRSIint.so	 libTNucleus.so        libTSuppressed.so     TGRSIFitDict_rdict.pcm    TLoopsDict_rdict.pcm	     TSRIMDict_rdict.pcm

where libTFormat.so and TFormatDict_rdict.pcm contain the definitions of the parent class TMnemonic.
The library that I then load which contains the daughter class is GRSIData/lib/libGRSIData.so:

GRSIData/lib:
libGRSIData.so		     libTGriffin.so	    libTPaces.so    libTTAC.so			       TCSMDict_rdict.pcm	       TLaBrDict_rdict.pcm     TSharcDict_rdict.pcm    TZeroDegreeDict_rdict.pcm
libMakeGriffinHistograms.so  libTGRSIDataParser.so  libTRF.so	    libTTigress.so		       TDescantDict_rdict.pcm	       TMidasDict_rdict.pcm    TSiLiDict_rdict.pcm
libTAngularCorrelation.so    libTGRSIDetector.so    libTS3.so	    libTTip.so			       TGenericDetectorDict_rdict.pcm  TPacesDict_rdict.pcm    TTACDict_rdict.pcm
libTCSM.so		     libTGRSIFormat.so	    libTSceptar.so  libTTriFoil.so		       TGriffinDict_rdict.pcm	       TRFDict_rdict.pcm       TTigressDict_rdict.pcm
libTDescant.so		     libTLaBr.so	    libTSharc.so    libTZeroDegree.so		       TGRSIDetectorDict_rdict.pcm     TS3Dict_rdict.pcm       TTipDict_rdict.pcm
libTGenericDetector.so	     libTMidas.so	    libTSiLi.so     TAngularCorrelationDict_rdict.pcm  TGRSIFormatDict_rdict.pcm       TSceptarDict_rdict.pcm  TTriFoilDict_rdict.pcm

And libTGRSIFormat.so and TGRSIFormatDict_rdict.pcm contain the definition of the daughter class TGRSIMnemonic.

(and thus the two _rdict.pcm files have the same name even though they are in two different directories). Could this be the issue?

Yes, this is most likely the issue.

But there isn’t a single file that corresponds to the library I’m loading as the library is several other libraries (with individual pcm files) linked together.

Fair enough. Did you use the flag:

-multiDict                    Enable support for multiple pcms in one library
                                Needs the -s flag. See its documentation.

when generating the dictionaries?

No, I most certainly did not. This is for the call to rootcint/rootcling, right? I will test that.

Seems that it’s not in the call to rootcint/rootcling as that gives me an error

Error: Multidict requested but no target library. Please specify one with the -s argument.

So how do I use this flag correctly?

Currently our makefile uses rootcint/rootcling to generate the dictionary, compiles the dictionary into an object file (.o), which is then used in the linking of the library. Then all the shared libraries are linked together to another shared library which we use. At which stage should the multiDict flag be used?

Additional arguments are needed. eg:

rootcling -f G__GenVector32.cxx
-s /opt/build/root_builds/rootcling.cmake/lib/libGenVector.so 
-multiDict 
-rml libGenVector.so 
-rmf /opt/build/root_builds/rootcling.cmake/lib/libGenVector32.rootmap 

I’m not sure where I’m supposed to get the .rootmap file from, but I tried adding the other flags following the pattern:

rootcling -f .build/libraries/GROOT/GROOTDict.cxx -c -I/helioshome/vbildste/Guelph/GRSISort-CentOs7/include -I/helioshome/vbildste/Guelph/GRSISort-CentOs7/users -DHAS_MATHMORE -DHAS_XML -s lib/libGROOT.so -multiDict -rml libGROOT.so -p GRootGuiFactory.h GRootFunctions.h GRootCommands.h GRootCanvas.h GRootBrowser.h GCanvas.h GH2Base.h GH2I.h GH2D.h GPeak.h GGaus.h GValue.h GH1D.h GNotifier.h GPopup.h GSnapshot.h TCalibrator.h GHSym.h GCube.h libraries/GROOT/LinkDef.h

Which gives me an error:

SysError in <TFile::TFile>: file lib/libGROOT_GROOTDict_rdict.pcm can not be opened (No such file or directory)

I don’t know where rootcling got the weird name from (there will be a lib/GROOTDict_rdict.pcm after the build is done). But isn’t the _rdict.pcm file generated by this call to rootcling?

EDIT: Okay, from rootcling -h I see that using -multiDict causes the -s flag to influence the name of the created pcm to be libTARGETLIBRARY_DICTIONARY_rdict.pcm (and in this case TARGETLIBRARY and DICTIONARY are both GROOT). So I changed the -s flag to be just -s libGROOT.so (without leading lib/), and the error is gone.

So after the program and the library were completely re-compiled I tried again, and I get the same crash and the stack trace is the same (memory addresses are different of course).

It is supposed to be generated by rootcling.

So after the program and the library were completely re-compiled I tried again

Did you also verify (and/or make sure) that now all the names of all _rdict.pcm files are unique?

Okay, I do see that these files get created. Still not sure what the right way is of adding them to the flag.

-s .build/libraries/GROOT/GROOT.so -multiDict -rml libGROOT.so

works and creates (amongst others) the files .build/libraries/GROOT/GROOT_GROOTDict_rdict.pcm and libGROOT.rootmap. Not sure why the latter is created in the main directory (where make is executed), maybe because I didn’t specify its path using the -rml flag?

But using that flag:

-s .build/libraries/GROOT/GROOT.so -multiDict -rml libGROOT.so -rml .build/libraries/GROOT/GROOT.rootmap

gives an Error: Opening new rootmap file libGROOT.so .build/libraries/GROOT/GROOT..rootmap_tmp_4304

Yes, these files now have all unique names.

-rml ....rootmap

should be using -rmf ‘f’ rather than ‘l’.

Also it could be that in your setup you need to use full pathname (maybe, maybe not)

Okay, using -rmf solved that issue. I now have both the .pcm and .rootmap file created in the same directory.
Currently our makefile is set up to copy all .pcm files into the same lib/ directory where all the shared object libraries of the program are. Should the .rootmap files also be copied into this directory?

EDIT: I tried copying the .rootmap files into the two different lib directories (the one for the main program and the one for the library that gets loaded), and I still get the same crash.

Should the .rootmap files also be copied into this directory?

yes.

and I still get the same crash.

humm … can you send the .pcm file that is supposed to contain info about TMnemonic

PS. and if I don’t see anything odd there, we will have to use gdb to understand why TProtoClass::Fill fails (or does not run) for that class …

The pcm file for TMnemonic is TFormat_TFormatDict_rdict.txt (12.7 KB)

The pcm file for TGRSIMnemonic is TGRSIFormat_TGRSIFormatDict_rdict.txt (2.8 KB)

I changed the extensions from pcm to txt to be able to upload them.

On the surface the files looks fine … which means we are not there yet :frowning:

humm …I just noticed:

#3  _GLOBAL__sub_I_TChannel.cxx(void) () at libraries/TGRSIFormat/TChannel.cxx:1410

What is on (and around) line 1410 of TChannel.cxx …

line 1410 is the closing bracket of

int TChannel::GetCrystalNumber() const
{
   if(fCrystalNumber > -1) {
      return fCrystalNumber;
   }

   fCrystalNumber = fMnemonic.Value()->NumericArraySubPosition();

   return fCrystalNumber;
}

Where did you get this information from? An old file? Because I had to rename the TGRSIFormat library to TFormat. And I just double checked using a grep for TGRSIFormat that this name now only appears in the sub-directory with the library that gets loaded later.

humm … maybe the code moved … I got this line number from the stack your provided by the use of SetClassSize:

#0  ROOT::TGenericClassInfo::GetClass (this=0x7ffff5f62140 <ROOT::GenerateInitInstanceLocal(TMnemonic const*)::instance>) at /opt/cern/root/root-6.14.04/core/meta/src/TGenericClassInfo.cxx:280
#1  0x00007ffff5d2f856 in TMnemonic::Class () at .build/libraries/TGRSIFormat/TGRSIFormatDict.cxx:946
#2  0x00007ffff5cd4471 in __static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535) at libraries/TGRSIFormat/TChannel.cxx:33
#3  _GLOBAL__sub_I_TChannel.cxx(void) () at libraries/TGRSIFormat/TChannel.cxx:1410
#4  0x00007ffff7deab03 in _dl_init_internal () from /lib64/ld-linux-x86-64.so.2
#5  0x00007ffff7ddc06a in _dl_start_user () from /lib64/ld-linux-x86-64.so.2
#6  0x0000000000000002 in ?? ()
#7  0x00007fffffffe256 in ?? ()
#8  0x00007fffffffe290 in ?? ()
#9  0x0000000000000000 in ?? ()

or maybe I am looking for what on line TGRSIFormat/TChannel.cxx:33 (stack #2).

Okay, that stack looks like this now:

#0  ROOT::TGenericClassInfo::GetClass (this=0x7ffff78d0140 <ROOT::GenerateInitInstanceLocal(TMnemonic const*)::instance>) at /opt/cern/root/root-6.14.04/core/meta/src/TGenericClassInfo.cxx:280
#1  0x00007ffff769d856 in TMnemonic::Class () at .build/libraries/TFormat/TFormatDict.cxx:946
#2  0x00007ffff7642471 in __static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535) at libraries/TFormat/TChannel.cxx:33
#3  _GLOBAL__sub_I_TChannel.cxx(void) () at libraries/TFormat/TChannel.cxx:1410
#4  0x00007ffff7deab03 in _dl_init_internal () from /lib64/ld-linux-x86-64.so.2
#5  0x00007ffff7ddc06a in _dl_start_user () from /lib64/ld-linux-x86-64.so.2
#6  0x0000000000000002 in ?? ()
#7  0x00007fffffffe256 in ?? ()
#8  0x00007fffffffe290 in ?? ()
#9  0x0000000000000000 in ?? ()

And line 33 of TChannel.cxx is:

TClass* TChannel::fMnemonicClass = TMnemonic::Class();

okay. That makes much more sense and indicate that creating a TClass from a rootpcm is not working correctly during library setup. You can work-around the problem by using:

TClassRef TChannel::fMnemonicClass(TMnemonic");