Different behavior between compiled and interpreted macro

Hello.

My macro accepts a txt file as input, which should contain a list of ROOT files (preceded by the protocol, if needed), one per line, to be chained together. However, I cannot execute it both compiled and interpreted: it works only when compiled.

Could you please tell me what is the problem?

Many thanks,
Diego

The code is the following:

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

#include "TROOT.h"
#include "TChain.h"
#include "TCint.h"
#include "TSystem.h"

int scanFiles(string list="") {

  if (list.empty()) {
    cerr << "Usage:" << endl
	 << "\troot[] .x scanFiles.C(\"list.txt\");       // from CINT" << endl
	 << "\t$ root -b -q \"scanFiles.C(\\\"list.txt\\\")\"  # from the shell" << endl;
    return -1;
  }

  gSystem->Load("libCintex.so");
  gROOT->ProcessLine("Cintex::Enable();");
  gSystem->Load("libTrigEventTPCnv.so");

  const char* chainName="YOUR CHAIN NAME HERE";

/// open TXT file
  ifstream txtfile(list.c_str());
  if (!txtfile.is_open()){
    cerr << "Error: cannot open " << list << endl;
    return -1;
  }

/// create the TChain
  TChain* chain = new TChain(chainName);

/// loop on lines, i.e. (protocol:) ROOT file names
  char tmp[256];
  int nFiles=0;
  while ((txtfile.getline(tmp, 256)).good()){
    cout << "Found " << tmp << endl; // DEBUG
    chain->Add(tmp); // add file to the chain
    ++nFiles;
  }

  txtfile.close();

  cout << "Found " << nFiles << " files. Chain has " 
       << chain->GetEntries() << " entries" << endl;

 // chain->Process("TSelector BASED CODE");

  return 0;
}

@@@@ Here is what happens when I call it in different ways:

root [0] .x scanFiles.C(“tmp.list”)
Error: non class,struct,union object txtfile used with . or -> scanFiles.C:45:
Error: non class,struct,union object txtfile.getline(tmp,256) used with . or -> scanFiles.C:45:
*** Interpreter error recovered ***

root [1] .x scanFiles.C+(“tmp.list”)
Info in : script has already been loaded in interpreted mode
Info in : unloading ./scanFiles.C and compiling it
Info in TUnixSystem::ACLiC: creating shared library ./scanFiles_C.so
FATAL 2008-Aug-16 13:46:56 [static void ers::ErrorHandler::SignalHandler::action(…) at ers/src/ErrorHandler.cxx:88] Got signal 11 Segmentation fault (invalid memory reference)

@@@@ This is quite strange, because if I don’t change it and use ROOT in batch mode this is what happens:

$ root -b -q “scanFiles.C+(“tmp.list”)”
(…)
Found 1 files. Chain has 9966 entries
(int)0

@@@@ But when I try again to let CINT interpret it:

$ root -b -q “scanFiles.C(“tmp.list”)”


  •                                     *
    
  •    W E L C O M E  to  R O O T       *
    
  •                                     *
    
  • Version 5.18/00a 20 February 2008 *
  •                                     *
    
  • You are welcome to visit our Web site *
  •      [root.cern.ch](http://root.cern.ch)            *
    
  •                                     *
    

ROOT 5.18/00a (branches/v5-18-00-patches@22235, Feb 21 2008, 21:46:00 on linux)

CINT/ROOT C/C++ Interpreter version 5.16.29, Jan 08, 2008
Type ? for help. Commands must be C++ statements.
Enclose multiple statements between { }.
root [0]
Processing scanFiles.C(“tmp.list”)…
Error: non class,struct,union object txtfile used with . or -> scanFiles.C:45:
Error: non class,struct,union object txtfile.getline(tmp,256) used with . or -> scanFiles.C:45:
*** Interpreter error recovered ***

@@@@ Now let’s try again from CINT, this time first asking it to load the macro, then to interpret it (the reverse order as before):

root [0] .x scanFiles.C+(“tmp.list”)
(…)
Found 1 files. Chain has 9966 entries
(int)0

root [1] .x scanFiles.C(“tmp.list”)
Error: Redefinition of default argument scanFiles.C:17:
*** Interpreter error recovered ***

Sorry.

I think I’ve found the problem: the formal input parameter was “list” that is probably conflicting with the STL container (?), even though I did not make any use of it.

Still, I cannot make the following sequences from CINT:

root [0] .x scanFiles.C(“tmp.list”) // OK it works
root [1] .x scanFiles.C+(“tmp.list”)
Info in : script has already been loaded in interpreted mode
Info in : unloading ./scanFiles.C and compiling it
FATAL 2008-Aug-16 15:48:55 [static void ers::ErrorHandler::SignalHandler::action(…) at ers/src/ErrorHandler.cxx:88] Got signal 11 Segmentation fault (invalid memory reference)

root [0] .x scanFiles.C+(“tmp.list”) // OK it works
root [1] .x scanFiles.C(“tmp.list”)
Error: Redefinition of default argument scanFiles.C:17:
*** Interpreter error recovered ***

Diego

[quote=“diego.casadei”]Hello.

My macro accepts a txt file as input, which should contain a list of ROOT files (preceded by the protocol, if needed), one per line, to be chained together. However, I cannot execute it both compiled and interpreted: it works only when compiled.

Could you please tell me what is the problem?

Many thanks,
Diego

The code is the following:

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

#include "TROOT.h"
#include "TChain.h"
#include "TCint.h"
#include "TSystem.h"

int scanFiles(string list="") {

  if (list.empty()) {
    cerr << "Usage:" << endl
	 << "\troot[] .x scanFiles.C("list.txt");       // from CINT" << endl
	 << "\t$ root -b -q "scanFiles.C(\\"list.txt\\")"  # from the shell" << endl;
    return -1;
  }

  gSystem->Load("libCintex.so");
  gROOT->ProcessLine("Cintex::Enable();");
  gSystem->Load("libTrigEventTPCnv.so");

  const char* chainName="YOUR CHAIN NAME HERE";

/// open TXT file
  ifstream txtfile(list.c_str());
  if (!txtfile.is_open()){
    cerr << "Error: cannot open " << list << endl;
    return -1;
  }

/// create the TChain
  TChain* chain = new TChain(chainName);

/// loop on lines, i.e. (protocol:) ROOT file names
  char tmp[256];
  int nFiles=0;
  while ((txtfile.getline(tmp, 256)).good()){
    cout << "Found " << tmp << endl; // DEBUG
    chain->Add(tmp); // add file to the chain
    ++nFiles;
  }

  txtfile.close();

  cout << "Found " << nFiles << " files. Chain has " 
       << chain->GetEntries() << " entries" << endl;

 // chain->Process("TSelector BASED CODE");

  return 0;
}

@@@@ Here is what happens when I call it in different ways:

root [0] .x scanFiles.C(“tmp.list”)
Error: non class,struct,union object txtfile used with . or -> scanFiles.C:45:
Error: non class,struct,union object txtfile.getline(tmp,256) used with . or -> scanFiles.C:45:
*** Interpreter error recovered ***

root [1] .x scanFiles.C+(“tmp.list”)
Info in : script has already been loaded in interpreted mode
Info in : unloading ./scanFiles.C and compiling it
Info in TUnixSystem::ACLiC: creating shared library ./scanFiles_C.so
FATAL 2008-Aug-16 13:46:56 [static void ers::ErrorHandler::SignalHandler::action(…) at ers/src/ErrorHandler.cxx:88] Got signal 11 Segmentation fault (invalid memory reference)

@@@@ This is quite strange, because if I don’t change it and use ROOT in batch mode this is what happens:

$ root -b -q “scanFiles.C+(“tmp.list”)”
(…)
Found 1 files. Chain has 9966 entries
(int)0

@@@@ But when I try again to let CINT interpret it:

$ root -b -q “scanFiles.C(“tmp.list”)”


  •                                     *
    
  •    W E L C O M E  to  R O O T       *
    
  •                                     *
    
  • Version 5.18/00a 20 February 2008 *
  •                                     *
    
  • You are welcome to visit our Web site *
  •      [root.cern.ch](http://root.cern.ch)            *
    
  •                                     *
    

ROOT 5.18/00a (branches/v5-18-00-patches@22235, Feb 21 2008, 21:46:00 on linux)

CINT/ROOT C/C++ Interpreter version 5.16.29, Jan 08, 2008
Type ? for help. Commands must be C++ statements.
Enclose multiple statements between { }.
root [0]
Processing scanFiles.C(“tmp.list”)…
Error: non class,struct,union object txtfile used with . or -> scanFiles.C:45:
Error: non class,struct,union object txtfile.getline(tmp,256) used with . or -> scanFiles.C:45:
*** Interpreter error recovered ***

@@@@ Now let’s try again from CINT, this time first asking it to load the macro, then to interpret it (the reverse order as before):

root [0] .x scanFiles.C+(“tmp.list”)
(…)
Found 1 files. Chain has 9966 entries
(int)0

root [1] .x scanFiles.C(“tmp.list”)
Error: Redefinition of default argument scanFiles.C:17:
*** Interpreter error recovered ***[/quote]

Hi Diego,

let me explain what you are trying to do :slight_smile:

You tell CINT to read a script, so it remembers all types and functions etc in that script. You run it. It in turn loads a library which in turn adds some scaffolding on top of CINT (talking Cintex here) that allows non-CINT dictionaries (talking Reflex here) to be piped into CINT. Amazingly enough all of that really works.

Now you ask CINT to reload the same script. Reloading means a) unloading, b) loading. The problem is with the unloading part. When unloading your script it must also unload all types that were defined afterwards, because they might depend on types defined in your script (where it doesn’t matter whether the earlier or later types are compiled or not). Again: CINT needs to remove everything it saw from the point of “.x scanFiles.C[+]”.

That includes your library with a Reflex dictionary, Reflex, and Cintex. And you have apparently hit an inconsistency that kicks in when you tear down the Reflex dictionaries after they have been set up. You are not just removing part of the reflex dictionaries here: you are removing Reflex itself and the scaffolding. So I am personally not too surprised that this fails.

Do you really need to do it that way? Can’t you first initialize the Cintex layer and load libTrigEventTPCnv.so and only then run your script? That way you should be able to reload as often as you want.

Cheers, Axel.