What is the matter with ROOT and char* or char[]?

I am trying to compile something using some root libraries. The classes that use GUI stuff are properly linked and dictionaries are created in the proper way. For a particular complicated class, I am not using any root libraries because I dont want to confuse cint or anyway mess up things more. Therefore it is not directly related to any root libraries, but indirectly, there has to be a connection with the gui and I include the header file AdcControl.h at some point to enable access to the AdcControl objects member functions . This is the only connection to ROOT.

The whole project is big and dependent on extra libraries and hardware. But the problem is localized so I hope there is something you have encountered before. The program compiles and runs ok if I have:

void AdcControl::testAdc(const int events)
{
	//some declarations omitted
	char base[] ="testPLAIN";
	char filename[FILENAME_MAX];
 
	sprintf(filename,"%s%s%de.dat",directory,base,events);
 
	if(writeFile==true){ 
		outf = fopen(filename,"w");
		if (!outf){
			printf("Cannot create data file! Not writing data file!\n");
			writeFile=false;
		} else
			printf("Writing in data file %s \n",filename);
	}
 
	printf("Starting ADC Test... \n");
	
//rest omitted

Let’s say I want to introduce another filename, to also write in a root file for example (even though I have said I wan to limit entanglement with root libraries). This introduces the following changes:

[code]void AdcControl::testAdc(const int events)
{

   //some declarations omitted

char base[] ="testPLAIN";
char filename[FILENAME_MAX];
char rootFileName[FILENAME_MAX];
sprintf(filename,"%s%s%de.dat",directory,base,events);
sprintf(rootFileName,"%s%s%de.root",directory,base,events);
if(writeFile==true){ 
	outf = fopen(filename,"w");
	if (!outf){
		printf("Cannot create data file! Not writing data file!\n");
		writeFile=false;
	} else
		printf("Writing in data file %s \n",filename);
}

if(writeRoot == true){
	printf("Writing rootfile as well\n");
}

printf("Starting ADC Test... \n");

//rest omitted

[/code]

Then the program still compiles, but on runtime I get the segmentation fault error:

[code]In test Adc. No of events: 10
Starting ADC Test…

*** Break *** segmentation violation
Using host libthread_db library “/lib64/tls/libthread_db.so.1”.
Attaching to program: /proc/5937/exe, process 5937
[Thread debugging using libthread_db enabled]
[New Thread 182957927872 (LWP 5937)]
0x00000033db98f5e4 in waitpid () from /lib64/tls/libc.so.6
#1 0x00000033db939a7f in do_system () from /lib64/tls/libc.so.6
#2 0x0000002a958fc6a1 in TUnixSystem::StackTrace ()
from /home/atlas/root/lib/libCore.so
#3 0x0000002a958f91ba in TUnixSystem::DispatchSignals ()
from /home/atlas/root/lib/libCore.so
#4
#5 0x00000000004122cb in AdcControl::testAdc (this=0xc4acd0, events=10)
at …/AdcControl.cxx:1958
#6 0x000000000041f1cc in AdcWindow::processAll (this=0xc4c180)
at …/AdcWindow.cxx:154
#7 0x00000000004280c7 in G__Dict_846_0_27 (result7=0xcceaa0, funcname=Variable “funcname” is not available.
)
at Dict.cxx:1174
#8 0x0000002a95fd0f2a in Cint::G__CallFunc::Execute ()
from /home/atlas/root/lib/libCint.so
#9 0x0000002a958e851c in TCint::CallFunc_Exec ()
from /home/atlas/root/lib/libCore.so
#10 0x0000002a9585364d in TQConnection::ExecuteMethod ()
from /home/atlas/root/lib/libCore.so
#11 0x0000002a95856940 in TQObject::Emit ()
from /home/atlas/root/lib/libCore.so
#12 0x0000002a98bd00f8 in TGButton::EmitSignals ()
from /home/atlas/root/lib/libGui.so
#13 0x0000002a98bcffc3 in TGButton::HandleButton ()
from /home/atlas/root/lib/libGui.so
#14 0x0000002a98c1ad3d in TGFrame::HandleEvent ()
from /home/atlas/root/lib/libGui.so
#15 0x0000002a98be91bb in TGClient::HandleEvent ()
from /home/atlas/root/lib/libGui.so
#16 0x0000002a98be92e7 in TGClient::ProcessOneEvent ()
from /home/atlas/root/lib/libGui.so
#17 0x0000002a98be939d in TGClient::HandleInput ()
from /home/atlas/root/lib/libGui.so
#18 0x0000002a98be93bd in TGInputHandler::Notify ()
from /home/atlas/root/lib/libGui.so
#19 0x0000002a958f9739 in TUnixSystem::DispatchOneEvent ()
from /home/atlas/root/lib/libCore.so
#20 0x0000002a95875b95 in TSystem::InnerLoop ()
from /home/atlas/root/lib/libCore.so
#21 0x0000002a9587594a in TSystem::Run () from /home/atlas/root/lib/libCore.so
#22 0x0000002a9581be0f in TApplication::Run ()
from /home/atlas/root/lib/libCore.so
#23 0x000000000040f041 in main (argc=Variable “argc” is not available.
) at …/MainControlMenu.h:157
[/code]

As you can see, the control goes up to the “Starting ADC test” printf checkpoint, even if the change was made before. AFter thet point there is a for loop that does everything but the control never gets into the loop. ALso the rest doesnt have anything to do with “rootFileName” or is this keyword anywhere mentioned. I changed the name as well.

Why does sometimes char* works and other times only char[] declaration of strings work? SOmetimes neither works. So what should I use: char* char[], string or TString?

Hi,

[Note that this is likely to be a C++ problem and not a ROOT problem per se]

What is the content of line 1958 of the file AdcControl.cxx?
(Also you might want to give a try to running your example with valgrind (valgrind.org))

Cheers,
PHilippe

I will thanks for the reply. But the output of the segmentation violation looks root-specific. How can I dissociate a class completely from root?

[quote]How can I dissociate a class completely from root?[/quote]No need to. The result is NOT root specific per se. What you are missing is that ROOT provide the stack trace printing but it does not (yet) alawys removing the stack printing code itself from the stack being printed. Namely you ought to just ignore the first few lines:0x00000033db98f5e4 in waitpid () from /lib64/tls/libc.so.6 #1 0x00000033db939a7f in do_system () from /lib64/tls/libc.so.6 #2 0x0000002a958fc6a1 in TUnixSystem::StackTrace () from /home/atlas/root/lib/libCore.so #3 0x0000002a958f91ba in TUnixSystem::DispatchSignals () from /home/atlas/root/lib/libCore.so #4 <signal handler called> which is the signal handling and stack printing. Then the outer stack is the way you called your routine#7 0x00000000004280c7 in G__Dict_846_0_27 (result7=0xcceaa0, funcname=Variable "funcname" is not available. ) at Dict.cxx:1174 #8 0x0000002a95fd0f2a in Cint::G__CallFunc::Execute () from /home/atlas/root/lib/libCint.so #9 0x0000002a958e851c in TCint::CallFunc_Exec () from /home/atlas/root/lib/libCore.so #10 0x0000002a9585364d in TQConnection::ExecuteMethod () from /home/atlas/root/lib/libCore.so #11 0x0000002a95856940 in TQObject::Emit () indicates that your code was triggering via the ROOT signal/slot mechanism.

This leaves your code:#4 <signal handler called> #5 0x00000000004122cb in AdcControl::testAdc (this=0xc4acd0, events=10) at ../AdcControl.cxx:1958 #6 0x000000000041f1cc in AdcWindow::processAll (this=0xc4c180) at ../AdcWindow.cxx:154 So since the signal handler is just under frame#5, we know that the crash was provoked by your code on line 1958 of AdcControl.cxx.

Cheers,
Philippe.

Yes thank you for the debugging help. It seems I was very quick to blame root for the problems, since I saw all that root-related output. I don’t know how, but it seems the extra character array definition is the think that brings the messy code to its knees. Bad pointer arithmetics in the code that follows must be the trigger for the segmentation fault. I don’t know why it was even there.

Anyway, I think it will be fine now, thanks for all the help!

Cheers,

Nik

In any case, I highly recommend either using C++ std::string or Root’s TString. It is very easy to introduce problems by using C style strings.

Cheers,
Charles

Indeed.