ROOT & stringstream

Hi,

I’m having some trouble running some code (appended below) that uses C stringstream in ROOT 6.06 on a Mac. The code is very similar to code that I used in ROOT 5, but, in ROOT 6, I get a number of strange behaviors.

the code is designed to read in a text file from an event generator (a modified STARlight) and produce an output NTUPLE: The input file has the format:

EVENT: 1 2 1
VERTEX: 0 0 0 0 1 0 0 2
GAMMA: 0.00663726 1.69041e-11
SOURCE: 0.001 0.001 9.96273 9.96273
TRACK:  8 -0.17838 0.224711 -1.89031 1 0 0 211
TRACK:  9 0.282689 -0.304921 -1.02322 1 1 0 -211

the code (below) successfully reads in the vertex line, but then the next line fails the assert:
assert(lineStream>>label>>epx>>epy>>epz>>ee);

This line has exactly the same format as the preceding lines; the only difference is that there are four double’s read in, rather than two. What’s going on?

The other problem occurs if I remove the matched /* …*/ so that the code near the bottom is uncommented. Then, I get a set of warnings, ending in a segmentation violation:

root [0] .x eTTreemaker.C
In file included from input_line_12:21:
In file included from /opt/local/libexec/root6/etc/root/dictpch/allHeaders.h:247:
In file included from /opt/local/libexec/root6/etc/root/cling/Interpreter/DynamicLookupRuntimeUniverse.h:19:
/opt/local/libexec/root6/etc/root/cling/Interpreter/Value.h:99:18: error: 
      C-style cast from 'long long' to 'auto' is not allowed
          return (T) V.getAs<long long>();
                 ^~~~~~~~~~~~~~~~~~~~~~~~
/opt/local/libexec/root6/etc/root/cling/Interpreter/Value.h:221:26: note: in
      instantiation of member function 'cling::Value::CastFwd<auto>::cast'
      requested here
      return CastFwd<T>::cast(*this);
                         ^
/opt/local/libexec/root6/etc/root/cling/Interpreter/DynamicLookupRuntimeUniverse.h:56:23: note: 
      in instantiation of function template specialization
      'cling::Value::simplisticCastAs<auto>' requested here
        return result.simplisticCastAs<T>();
                      ^
/opt/local/libexec/root6/etc/root/cling/Interpreter/DynamicLookupRuntimeUniverse.h:47:7: note: 
      in instantiation of function template specialization
      'cling::runtime::internal::EvaluateT<auto>' requested here
    T EvaluateT(DynamicExprInfo* ExprInfo, clang::DeclContext* DC ) {
      ^
/opt/local/libexec/root6/etc/root/cling/Interpreter/RuntimeUniverse.h:50:7: note: 
      in instantiation of member function 'cling::runtime::internal::EvaluateT'
      requested here
      int InterpreterGeneratedCodeDiagnosticsMaybeIncorrect;
      ^
In file included from input_line_12:21:
In file included from /opt/local/libexec/root6/etc/root/dictpch/allHeaders.h:247:
In file included from /opt/local/libexec/root6/etc/root/cling/Interpreter/DynamicLookupRuntimeUniverse.h:19:
/opt/local/libexec/root6/etc/root/cling/Interpreter/Value.h:101:18: error: 
      C-style cast from 'unsigned long long' to 'auto' is not allowed
          return (T) V.getAs<unsigned long long>();
                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/local/libexec/root6/etc/root/cling/Interpreter/Value.h:103:18: error: 
      C-style cast from 'double' to 'auto' is not allowed
          return (T) V.getAs<double>();
                 ^~~~~~~~~~~~~~~~~~~~~
/opt/local/libexec/root6/etc/root/cling/Interpreter/Value.h:105:18: error: 
      C-style cast from 'float' to 'auto' is not allowed
          return (T) V.getAs<float>();
                 ^~~~~~~~~~~~~~~~~~~~
/opt/local/libexec/root6/etc/root/cling/Interpreter/Value.h:107:18: error: 
      C-style cast from 'long double' to 'auto' is not allowed
          return (T) V.getAs<long double>();
                 ^~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/local/libexec/root6/etc/root/cling/Interpreter/Value.h:110:18: error: 
      C-style cast from 'size_t' (aka 'unsigned long') to 'auto' is not allowed
          return (T) (size_t) V.getAs<void*>();
                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 *** Break *** segmentation violation
 Generating stack trace...
An admin user name and password is required to enter Developer Mode.
Admin user name (sklein): 

Needless to say, this is totally undiagnostic. It also seems strange, since the code is almost entirely numerical expressions - nothing that would normally cause this type of problem.

Any pointers to the root (pardon the pun) of the problem(s) and/or suggestions for fixes would be greatly appreciated.

Spencer

// this macro runs analyze.cxx, which takes as input an Ascii e-starlight output
// file, slight.out, and creates a standard TTREE
// S. Klein, September, 2017

{

#include <TMath.h>
#include <iostream>
  using namespace std;
  double me=0.000511;  //electron mass

// create output TTree here
  
  double epx,epy,epz,eprap,ppx,ppm,ppe,fspx,fspy,fspz,fse,fsrap,fspt,fsmass,p1x,p1y,p1z,p1e,p1prap;
  double p2x,p2y,p2z,p2e,p2prap;
  double ee,ept,ptp1,p2pt;

  TNtuple *esNTuple = new TNtuple("eslightNtuple","eslightNtuple","ept:epz:eprap:ppm:ppe:fspt:fspz:fsrap:fsmass:p1pt:p1z:p1prap:p2pt:p2z:p2prap");
// This is the electron, photon, final state (particle combination), particle 1 and particle 2
// These are pseudorapidities, except for the final state, where it is rapidity
// For the photon there are only two quantities - the mass and the energy

   cout <<" Opening slight.out"<< endl;

   ifstream inFile;
   inFile.open("slight.out");
   cout << "slight.out open"<<endl;
   int countLines=0;

  
 // Define variables for event loop
   int ntrk,nvtx;
   int i1,i2,i3,i4;  // junk variables for fscanf lines

  
// begin event loop here.  eSTARlight events have the format:
// Event card, Vertex card, photon card, source card, track 1 card, track 2 card

   while (inFile.good())
      {
 	string line;
	stringstream lineStream;
  
 // event card
	string label;
	int eventNmb,nmbTracks, pcode;
	int nev,ntr,stopv,pdgpid;
	if (!getline(inFile,line)) {break;}
	countLines++;
	lineStream.str(line);
	assert(lineStream>>label>>eventNmb>>nmbTracks);
	if (!(label =="EVENT:")) continue;
	if (eventNmb < 5) {cout <<"Reached Event "<<eventNmb<<endl;}
	
 // vertex card
	if (!getline(inFile,line)) {break;}
    	countLines++;
	lineStream.str(line);
	assert(lineStream>>label);
	assert(label == "VERTEX:");
	
//  gamma card
	if (!getline(inFile,line)) {break;}
    	countLines++;
	lineStream.str(line);
	assert(lineStream>>label>>ppe>>ppm);
	assert(label == "GAMMA:");
	if (eventNmb < 5) {cout <<"Gamma reads "<<ppe<<ppm<<endl;}

// Electron card
	if (!getline(inFile,line)) {break;}
    	countLines++;
	lineStream.str(line);
	assert(lineStream>>label>>epx>>epy>>epz>>ee);
	assert(label == "SOURCE:");
	if (eventNmb < 5) {cout <<"SOURCE: reads "<<epx<<epy<<epz<<ee<<endl;}

// two track cards
	if (!getline(inFile,line)) {break;}
    	countLines++;
	lineStream.str(line);
	assert(lineStream>>label>>pcode>>p1x>>p1y>>p1z>>i1>>i2>>i3>>pdgpid);
	assert(label == "TRACK:");
	
	if (!getline(inFile,line)) {break;}
    	countLines++;
	lineStream.str(line);
	assert(lineStream>>label>>pcode>>p2x>>p2y>>p2z>>i1>>i2>>i3>>pdgpid);
	assert(label == "TRACK:");

// Now do needed kinematics computations

	double psq,e,p;	
	psq=epx*epx+epy*epy+epz*epz;

        e=sqrt(psq+me*me);
        p=sqrt(psq);
        eprap=0.5*log((p+epz)/(p-epz));

        double p1p;
	p1p=sqrt(p1x*p1x+p1y*p1y+p1z*p1z);
	/*
        p1rap=0.5*dlog((p1p+p1z)/(p1p-p1z));

	p1pt=sqrt(p1x*p1x+p1y*p1y);

        p=sqrt(p2x*p2x+p2y*p2y+p2z*p2z);
        p1rap=0.5*log((p+p2z)/(p-p2z));
	p2pt=sqrt(p2x*p2x+p2y*p2y);

	ept=sqrt(epx*epx+epy*epy);

 // final state
        fspx=p1x+p2x;
        fspy=p1y+p2y;
        fspz=p1z+p2z;
        fse=p1e+p2e;
        fspt=dsqrt(fspx*fspx+fspy*fspy);
        fsmass=dsqrt(fse*fse-(fspx*fspx+fspy*fspy+fspz*fsp));
        frap= 0.5*log((fse+fsepz)/(fse-fsepz));
	// done - now book NTuple

	*/
	esNTuple->Fill(ept,epz,eprap,ppm,ppe,fspt,fspz,fsrap,fsmass,p1pt,p1z,p1prap,p2pt,p2z,p2prap);

	if (eventNmb < 5)
	   { cout <<ppe<<ppm<<endl;
	    cout<<epx<<epy<<epz<<eprap<<endl;
	    cout<<fspx<<fspy<<fspz<<fse<<fsrap<<fspt<<fsmass<<fsrap<<endl;
	    cout<<p1x<<p1y<<p1z<<p1prap<<endl;
	    cout<<p2x<<p2y<<p2z<<p2prap<<endl;
	   }
	
      } //Done with event loop.
		   
// write out NTuple

 TFile *NTfile = new TFile("ntuple.root","r");
 esNTuple->Write();
 NTfile->Close();
}

Try:

#include <TFile.h>
#include <TNtuple.h>
#include <TMath.h>
#include <cmath>
#include <cassert>
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
void analyze(void)
{
  double me=0.000511;  //electron mass
  // ...
}

Wile is right about the includes.

I’d like to add:
void analyze(void) is C style, in C++ void analyze() is sufficient / identical.

Some more comments:

    ifstream inFile;
    inFile.open("slight.out");
    cout << "slight.out open" << endl;

You aren’t checking the result - but you are printing that the file is open. So why not:

    auto inFileName = "slight.out";
    ifstream inFile(inFileName);
    if (inFile.is_open()) {
        cout << inFileName << " opened\n";
    } else  {
        cout << "couldn't open " << inFileName << "\n";
        // insert code to handle error
    }

And a real bug: you are using assert with side effects!
Assert is for asserting internal program logic only, not for checking some input results! Asserts can be removed from code completely in release builds. Try assert(0) in a interactive ROOT6 command line - it does nothing.
So do NOT write assert(lineStream >> label);!
instead call some other (own) function taking a boolean.

1 Like

Dear Wile (Simon?) and Wolf:

Thank you for your helpful replies. Adding the #include’s suggested by Wile fixed the second problem, but did not affect the first. Nor did removing the assertion help. The relevant code now reads:

// Electron card
if (!getline(inFile,line)) {break;}
countLines++;
lineStream.str(line);
//assert(lineStream>>label>>epx>>epy>>epz>>ee);
lineStream>>label>>epx>>epy>>epz>>ee;
if (eventNmb < 5) {
cout<<line<<endl;
cout <<"SOURCE: reads “<<label<<” “<<epx<<” “<<epy<<” “<<epz<<” "<<ee<<endl;
}
assert(label == “SOURCE:”);

and produces the following output:

Opening slight.out
slight.out open
Reached Event 1
Gamma reads 0.006637261.69041e-11
SOURCE: 0 0 9.96273 9.96273
SOURCE: reads GAMMA: 1.89227e-321 1.97626e-323 2.29311e-314 6.95322e-310
Assertion failed: (label == “SOURCE:”), function eTTreemaker, file /Users/sklein/estarlight/STARlight/trunk/build/eTTreemaker.C, line 90.
SRKlein-m87:build sklein$

In other words, ‘line’ is read in correctly, but somehow the linestream command is going awry on the third use here. ‘label’ is not reassigned, and the four doubles are garbage.

The assertion was failing because it should. I can remove the other assertions and check for file opening in the preferred manner, but I don’t think that either of those things is causing the problem.

Spencer

Any more ideas?

Spencer

This happens because you exhaust the stringstream in the previous line, i.e. the eofbit gets set. That isn’t cleared by the str() function and thus followings reads will fail.

Two simple possible solutions:
a) replace all lineStream.str(line); with lineStream.str(line); lineStream.clear();
or b) replace all lineStream.str(line); with lineStream = stringstream(line);

You can see where this behavior comes from here:

root [0] stringstream ss("42");
root [1] int i; ss >> i;
root [2] ss.rdstate()
(std::ios_base::iostate) (std::_Ios_Iostate::_S_eofbit) : (int) 2
root [3] (bool)ss
(bool) true
root [4] ss.str("23");
root [5] ss.rdstate()
(std::ios_base::iostate) (std::_Ios_Iostate::_S_eofbit) : (int) 2
root [6] (bool) (ss >> i)
(bool) false
root [7] i
(int) 42
root [8] ss.clear(); (bool) (ss >> i)
(bool) true
root [9] i
(int) 23

And more things: while copying your code in an editor, I noticed that the variable p1pt was not declared, instead there are a lot of unused variables. Consider cleaning this up a bit.
Also, I assume your input file is small. Otherwise I would first open the file, then create the TNTuple (and opening with “r” - should that read “recreate”?).

Dear Wolf:

Thank you very much for the clear explanation and pointer for a fix. I was able to get the lineStream=stringstream(line) approach to work.

I will certainly clean up my code once it is working - until I got this help, I had not been able to get to the point of debugging the guts of it.

Spencer

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