Trunk@40894

The “trunk@40894” is exactly my problem (there is no any problem in v5-28-00-patches, nor in ROOT 5.18).
If this is not a problem in the newest root(cint) then what?
Looking at the output of the ROOT trunk@40894 make command, I can see no errors reported. Everything was built and installed fine (except xrootd which I had to “disable”).
As shown in my post of “Sat Sep 17, 2011 15:49”, g++ compiles my newest macro fine (the one attached on “Sat Sep 17, 2011 14:54”), even with “-ansi -pedantic” there is no single complain related to it.

Hi Pepe,

I had tried with a simplistic constructor (taking just an int as argument), indeed the (old) limitation in CINT that you can not constructed an array of object with ‘complex’ constructor, i.e:const MyClass Data[] = { MyClass("a", 0.0, MyClass::k_T_a, MyClass::k_P_a), MyClass("b", 1.0, MyClass::k_T_b, MyClass::k_P_b), MyClass("U", 2.0, MyClass::k_T_U, MyClass::k_P_U) };is still not supported. The following version works for me in rootcint:#ifdef __CINT__ const MyClass Data[3]; #else const MyClass Data[] = { MyClass("a", 0.0, MyClass::k_T_a, MyClass::k_P_a), MyClass("b", 1.0, MyClass::k_T_b, MyClass::k_P_b), MyClass("U", 2.0, MyClass::k_T_U, MyClass::k_P_U) }; #endif

Cheers,
Philippe.

Yes, I also noticed it, too.
The problem is that in my “real macro”, I do not know how many entries are there.
There are a lot if “#ifdef” / “#else” / …, and so the exact number of entries is unknown in advance, it can even be zero (it’s decided at compile-time and so I do not want to hardcode any number for CINT, and I cannot say “const MyClass Data[0];”.

What about:

#ifdef CINT
const MyClass *Data;
#else
const MyClass Data[] = { …, …, … };
#endif

Will this be safe enough?

And why does “extern const Myclass Data[];” kill the newest rootcint?

Do you need the dictionary for ‘Data’? I.e. does it need to be directly accessible from the interpreter?

Philippe.

Basically, yes, I would like to be able to access Data internals from within CINT.
The “core” of the computational code is ACLiC-(pre)compiled.
But then, the “management” is done by (cint) interpreted macros.

O.K. I’ve just found that replacing “const MyClass Data[];” with “const MyClass *Data;” is not an option at all (even with an additional “extern”, tested in v5-28-00-patches).
Although it seems “natural” … and in both cases I can write “Data[some_number]” … when used in CINT, in the first case I will get the proper Data entry while in the second case I will get a complete trash.

The funny thing is that the newest rootcint actually generates “proper” dictionary files for the “const MyClass Data[];” case (I can see them with gDebug=7 and they have pretty much the same contents as in the case of the working ROOT 5.28 and 5.18), but then it dies with a segmentation violation (and so the newest root sees an error).

I’m afraid I will really need to say “const MyClass Data[99999999];” then.

Well, just an update … 99999999 kills rootcint … rootcint really tries to allocate that array using a malloc! Even if I say “extern const MyClass Data[99999999];” I get:
Internal Error: malloc failed for Data[99999999] …

[quote]but then it dies with a segmentation violation (and so the newest root sees an error).[/quote]yes, it now incorrectly ‘delete’ it …

[quote]Basically, yes, I would like to be able to access Data internals from within CINT.[/quote]I would recommend that rather than giving direct access to the (real) global variable in the interpreter you wrap it with a (few) functions. So something like (in spirit):[code]#ifndef CINT
const MyClass Data[] = { … }
const Int_t NData = …;
#else
const Int_t NData;
#endif

MyClass &GetData(Int_t index) {
if (index > NData) { Fatal(“GetData”,"%d is out of bounds (%d)",index,NData); }
return Data[index];
}[/code]

Cheers,
Philippe.

O.K. I will rethink about the way I use Data.

Anyhow, can you explain why rootcint allocates an array (when creating the dictionary source code) even if I say it’s “extern”:
extern const MyClass Data[99999999];

If I say 9999999, I no longer get the malloc error, but rootcint works for a really looooong time.

If it’s “extern”, it should simply register the “pointer”.

Hi,

I can not reproduce the problem with extern. For me it neither crash nor take a long time.

Cheers,
Philippe.

O.K. Can you try MyMacro.cxx and modify it:

#if !defined(__CINT__) const MyClass Data[] = { MyClass("a", 0.0, MyClass::k_T_a, MyClass::k_P_a), MyClass("b", 1.0, MyClass::k_T_b, MyClass::k_P_b), MyClass("U", 2.0, MyClass::k_T_U, MyClass::k_P_U) }; const int NData = (sizeof(Data) / sizeof(MyClass)); #else const int NData; extern const MyClass Data[999999999]; #endif

What I get is ():

root [0] .L MyMacro.cxx++
Info in TUnixSystem::ACLiC: creating shared library /…/./MyMacro_cxx.so
Internal Error: malloc failed for Data[999999999] MyMacro.cxx:15:
Warning: Error occurred during reading source files
Warning: Error occurred during dictionary source generation

If I reduce 999999999 to 9999999, I no longer get this error.
Well, with “MyMacro.cxx”, I cannot reproduce the loooong time … but with my “original macro” …

With “extern const MyClass Data[9];”, ACLiC needs just 1.5 seconds to create the shared library.
With “extern const MyClass Data[9999999];”, ACLiC needs 17 seconds (and with gDebug=7 I can clearly see that it’s the rootcint which uses all that time).

Hi,

I can indeed reproduce the problem this way (I must have used either too small a number or too much a simplification of MyClass). Both symptom (malloc error and slowness) are indeed to the array being allocated despite the extern.

Cheers,
Philippe.

Just one additional note.
ROOT v5-28-00-patches behaves the same way, so it’s not something that was just introduced in the newest rootcint.

Hi,

When generating the dictionary CINT wants/needs to know the size of the variable. In its currently implementation it does allocate the underlying memory in order to know … This is indeed yet another deficiency in CINT (and its data model) that we do not intend to attempt to fix with the confine of the CINT code itself.

Cheers,
Philippe.

Many thanks for all your help.
Knowing all the (new and old) root(cint) limitations now, I think I designed a new “standard” way of dealing with problems like that (it works in any ROOT version, old and new).
It is very easy to implement (i.e. modifying of the existing code is trivial) and it doesn’t break anything in my existing code.

#if !defined(__CINT__) static const MyClass _static_const_MyClass_Data_[] = { MyClass("a", 0.0, MyClass::k_T_a, MyClass::k_P_a), MyClass("b", 1.0, MyClass::k_T_b, MyClass::k_P_b), MyClass("U", 2.0, MyClass::k_T_U, MyClass::k_P_U) }; const int NData = (sizeof(_static_const_MyClass_Data_) / sizeof(MyClass)); const MyClass *Data = _static_const_MyClass_Data_; // Data[NData] #else const int NData; const MyClass *Data; // Data[NData] #endif

BTW. Your explanations about how CINT treats the “extern” make it also clear why the newest rootcint dies with a segmentation violation when it encounters a declaration like “extern MyClass MyData[];” (the “old-fashioned” rootcint survives it fine, as reported in my earlier post of “Sat Sep 17, 2011 19:14” here).