RE: Question about static class objects

From: Philippe Canal <pcanal_at_fnal.gov>
Date: Tue, 27 May 2008 13:59:52 -0500


Hi Tom,

> Apparently I simplified it too much, and you took issue with C++ style
> rather than the actual problem (though your workaround does work).

Actually I did not take issue with C++ style [really :) I did not], I was merely mentioning thatthe only working work-around within CINT just happens to be better style :)
(i.e. it is not important compared to the fact that one work and one does not)

> I'm astounded this has not come up before -- this is a standard
> way to keep track of all instances of class Zap.

It actually has been already encountered before and partially fixed. However
this is a difficult/intrigate issue and we decided to postpone a real complete solution until the merge with Reflex is done (especially since there
is a perfectly valid (and arguably better :)) work-around)

> Making list not be a class variable, but rather a local static object in
> an accessor function (as you suggest), complicates the code more than I
> want to do (list is used several dozen times, and there are three such
> TList-s).

This is indeed unfortunate :(. Hopefully, in the example I provided, the change needed on the call site is minimal (replace 'list' with 'list()')

> Note that making try() not inline (separating its definition from the
> class declaration) did not help.

Indeed, this won't work any better, the issue is that the initialization/constructor
of the object is not done correctly.

Cheers,
Philippe.

PS.
> The above code is straightforward, reasonable, and standard C++,
> and it ought to work; I'm astounded this has not come up before --
> this is a standard way to keep track of all instances of class Zap.

Well :), even in C++, this has many caveat, you have no control/guarantee of when the class static data member will be initialized and using this member during the shared library loading is __in C++__ undefined behavior.
And, yes, this does not apply to your specific case and CINT ought to function properly in this case; it does not and it is hard to fix :(

-----Original Message-----
From: owner-roottalk_at_root.cern.ch [mailto:owner-roottalk_at_root.cern.ch] On Behalf Of Tom Roberts
Sent: Tuesday, May 27, 2008 1:45 PM
To: 'ROOT Talk'
Subject: Re: [ROOT] Question about static class objects

Apparently I simplified it too much, and you took issue with C++ style rather than the actual problem (though your workaround does work). In my real code, list is used only within class Zap, and that fails:

file zap.C now contains:

     class Zap {
         static TList list;
     public:
         static void try() {
             list.Clear();
         }
     };
     TList Zap::list;

$ root -l
The Root User's Guide is at /Users/tjrob/root/Root_Users_Guide_5_12.pdf root [0] .L zap.C
root [1] Zap::try()

Note that making try() not inline (separating its definition from the class declaration) did not help.

This happens to be root 5.14 on Mac OS X (Tiger), but the problem exists in 5.16 and 5.18 on Linux as well (and probably other releases and OSs).

Making list not be a class variable, but rather a local static object in an accessor function (as you suggest), complicates the code more than I want to do (list is used several dozen times, and there are three such TList-s). But I suppose I can put a non-static TList& into the class and initialize it as you suggest. The above code is straightforward, reasonable, and standard C++, and it ought to work; I'm astounded this has not come up before -- this is a standard way to keep track of all instances of class Zap.

Tom Roberts

Philippe Canal wrote:
> Hi Tom,
>
> Use:
>
> class Zap {
> public:
> TList &list();
> };
>
> TList &Zap::list() {
> static TList list;
> return list;
> }
>
> which anyway is slightly better in term of C++ style :)
>
> Cheers,
> Philippe.
>
> -----Original Message-----
> From: owner-roottalk_at_root.cern.ch [mailto:owner-roottalk_at_root.cern.ch] On
> Behalf Of Tom Roberts
> Sent: Monday, May 26, 2008 1:12 PM
> To: 'ROOT Talk'
> Subject: [ROOT] Question about static class objects
>
> I am puzzled why this fails (Root 5.16 or 5.18, on Fedora Core 8).
>
> file zap.C contains:
> class Zap {
> public:
> static TList list;
> };
> TList Zap::list;
>
> $ root -l
> root [0] .L zap.C
> root [1] Zap::list.Clear();
> *** Break *** segmentation violation [....]
>
> But this works:
> $ root -l
> root [0] TList zap;
> root [1] zap.Clear();
> root [2] .q
>
>
> Any suggestions how to work around this?
>
>
> Tom Roberts
>
>
Received on Tue May 27 2008 - 21:00:11 CEST

This archive was generated by hypermail 2.2.0 : Thu May 29 2008 - 17:50:01 CEST