ROOT 5.18 Fault When Saving User Input as String (Windows)

Hi,
I am writing a compiled application using ROOT 5.18. I want to store a user specified file name as a string. Unfortunately, the program only seems to work when I hard code the file name as a string. When I try to get a user specified input and store it as a string, I get a STACKTRACE output and the program obviously crashes. I have the following #includes in the *.cpp file where my main() function is:

#include <cctype>
#include <iostream>
#include <sstream>
#include <string>

// ROOT Includes
#include "TCanvas.h"
#include "TAxis.h"
#include "TH2D.h"
#include "TObject.h"
#include "TStyle.h"
#include "TROOT.h"
#include "TRint.h"
#include "TApplication.h"

Additionally, I have tried two different ways of storing the user input in a string. The following two user calls are:

string filename;
cout<<"Please enter the name of your file: ";
getline(cin,filename);

which produces:

==========================================
=============== STACKTRACE ===============
==========================================


================ Thread 0 ================
  libCore!std::basic_istream<char,std::char_traits<char> >::sentry::sentry()
  libCore!??$getline@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@YAAAV?$basic_
istream@DU?$char_traits@D@std@@@0@AAV10@AAV?$basic_string@DU?$char_traits@D@std@
@V?$allocator@D@2@@0@@Z()
  f:\rtm\vctools\crt_bld\self_x86\crt\src\crtexe.c(586): __tmainCRTStartup()
  kernel32!RegisterWaitForInputIdle()

================ Thread 1 ================
  ntdll!KiFastSystemCallRet()
  kernel32!WaitForSingleObject()
  libCore!`anonymous namespace'::HandleConsoleThread()
  0xffffffffe87c8024 ??

================ Thread 2 ================
  ntdll!KiFastSystemCallRet()
  kernel32!Sleep()
  libCore!TWinNTSystem::TimerThread()

================ Thread 3 ================
  ntdll!KiFastSystemCallRet()
  libCore!`anonymous namespace'::GetProgramCounter()
  0xffffffffff006aec ??

==========================================
============= END STACKTRACE =============
==========================================

And the other is:

string filename;
cout<<"Please enter the name of your file: ";
cin>>filename;

Which produces:

==========================================
=============== STACKTRACE ===============
==========================================


================ Thread 0 ================
  libCore!std::basic_istream<char,std::char_traits<char> >::sentry::sentry()
  f:\xinray_data\andrew\field_emission\emission\emission\emission.cpp(172): main
()
  f:\rtm\vctools\crt_bld\self_x86\crt\src\crtexe.c(586): __tmainCRTStartup()
  kernel32!RegisterWaitForInputIdle()

================ Thread 1 ================
  ntdll!KiFastSystemCallRet()
  kernel32!WaitForSingleObject()
  libCore!`anonymous namespace'::HandleConsoleThread()
  0xffffffffe87c8024 ??

================ Thread 2 ================
  ntdll!KiFastSystemCallRet()
  kernel32!Sleep()
  libCore!TWinNTSystem::TimerThread()

================ Thread 3 ================
  ntdll!KiFastSystemCallRet()
  libCore!`anonymous namespace'::GetProgramCounter()
  0xffffffffff006aec ??

For both of these input methods, I do not have time to even begin typing a file name. Both failures occur the minute the cin prompt comes up. Any thoughts or help on this matter would be greatly appreciated.

Thanks,
Andrew

I have found that a temporary fix can be used as a workaround for this issue. If I direct the user input to a char* object, I can then convert that char* input into a string input with a custom toString() function as follows.

[code]template
std::string toString(T toBeConverted){

// create an out string stream
std::ostringstream buffer;
// write the value to be converted to the output stream
buffer << toBeConverted;
// get the string value 
return buffer.str();

}
[/code]

While this works, I am curious as to why directly handling user input with std::string causes so much difficulty in ROOT.
Andrew

Hi,

This should a priori work. Which compiler (version) are you using? How did you compile your code? (I.e. I am suspect a mis-match in compiler switches).

Cheers,
Philippe.

I am using Visual Studio 2005. There is potentially some compiler switch mismatching. For the release build, my flags are:

/O2 /GL /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /FD /EHsc /MD /Fo"Release\\" /Fd"Release\vc80.pdb" /W0 /nologo /c /Wp64 /Zi /TP /errorReport:prompt

I usually program in linux, so I am not sure what all this means. Also, some of the other people who use this computer have Chinese support enabled. I have no idea if this is a factor, but perhaps it will help shed some light on the issue. As you know before, it took me some time to figure out the _DEBUG preprocessor flag was set. Thanks again for your help.
Cheers,
Andrew

Hi,

We build with: cl -O2 -nologo -FIw32pragma.h -MD -GR -G5 -EHsc-
The extra /Zi is most likely a problem (request debug symbols).
The missing ‘-GR’ is a possible problem. I don’t know what /FD does.

Cheers,
Philippe.

I have taken into account the suggestions you have made. However, I am still experiencing the same issue with string input. My updated flags are shown below.

Apparently the /GR flag is implied. I think the /FD flag needs to be removed, but I am not sure how manually edit the command line flags in Visual Studio. From the msoft documentation I found this about the /FD flag.

[quote]/FD ensures that the .idb file has sufficient dependency information. /FD is only used by the development environment, and it should not be used from the command line or a build script.
[/quote]

For now I think I have all the flags you do. I was also told by the C++ freenode channel that msoft officially states in their documentation not to use std + dll unless using std::vector.

Cheers,
Andrew

Hi Andrew,

Can you send me a project file (and the source) reproducing the problem?

Thanks,
Philippe.

Hi,

also make sure that you are not using a debug version of ROOT together with your optimized program. Microsoft’s STL is incompatible between debug / non debug (=release). That could explain why you see crashes in STL code.

Cheers, Axel.

Axel,
Thanks for the tip, that was it!
Cheers

As far as I can tell, this is not valid C++:

cplusplus.com/reference/iost … m/getline/

istream& getline (char* s, streamsize n );
istream& getline (char* s, streamsize n, char delim );

So passing in a C++ string won’t work (and shouldn’t compile).

Cheers,
Charles

Hi Charles,

You are referring to the member function istream::getline, whereas there is also a std::getline whose signature is:

Cheer,
Philippe