This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Static C++ object in (different) optimized libraries



A common construct for C++ programmer is a template called Singleton.

    /**
    * Singleton design pattern class
    **/
    template<class SINGLECLASS>
    class Singleton
    {
    public:
        static SINGLECLASS& instance();

    protected:
        inline Singleton(){}
        inline ~Singleton(){}
    };

    template<class SINGLECLASS>
    SINGLECLASS& Singleton<SINGLECLASS>::instance()
    {
        static SINGLECLASS s_instance;
        return s_instance;
    }

class MyClass : public Singleton<MyClass>
{
public:
    MyClass() {}
};

Now, if I call MyClass::instance() from different libraries and the executable (probably different optimizations), the compiler/linker forces inlining
and I can observe multiple constructor calls at the line "static SINGLECLASS s_instance" which is supposed to happen just once per template parameter (SINGLECLASS) type.

  • Are you observing that within a multithreading implementation? If yes, then f.e. read Scott Meyers C++ and the Perils of Double-Checked Locking - the singleton pattern - at least in the classic way you've implemented this pattern) is not commonly thread-safe, this is an implementation detail of the compiler, f.e. read here.

    Regards,
    Joern.

  • No, it is single threaded so far. Not multithreaded.

    I've found similar problems with statics, see:

    http://e2e.ti.com/support/development_tools/compiler/f/343/t/159199.aspx#584748

    Best regards

    Thomas

  • Are you using COFF ABI or EABI?

  • I want to be absolutely clear on what problem you are facing.  Could you please clarify the following statement?

    Thomas S said:

    Now, if I call MyClass::instance() from different libraries and the executable (probably different optimizations), the compiler/linker forces inlining
    and I can observe multiple constructor calls at the line "static SINGLECLASS s_instance" which is supposed to happen just once per template parameter (SINGLECLASS) type.

    Are you saying that:

    • for a given class X, you have multiple call sites to Singleton<X>::instance() in your  source code
    • all of which get inlined
    • and each call site results results in a call to the default constructor for Singleton<X>?

    Does this also happen for a non-template class?

    Are you using RAM model?

  • Actually, the problem appears either in RAM or ROM model.

    The normal use case for a singleton is, that several parts of code need access to the single object. So, yes multiple source code parts call MyClass::instance(). And this should return the single static instance. In my case I got the problem when these calles are done from files in different libraries, some with optimizations turned on and later linked together. So, the optimized ones are inlined and MyClass::instance returns two different objects with different addresses. The MyClass::MyClass() constructor is called twice in MyClass::instance().

    Unfortunately, I don't have the time for further testing of this problem or create test projects to reproduce this problem. My projects, on which I observe this problem, is quite big.

    Although this implementation seemed to work with TMS320C6xxx compiler in former projects I worked on, I found a workaround with a different Singleton implementation, that seems not to produce this problem on TI ARM compiler (unfortunately this uses the heap and for embedded I prefere static memory where possible).

    /**
    * Singleton design pattern class
    **/
    template<class SINGLECLASS>
    class Singleton
    {
    public:
    static SINGLECLASS& instance();

    protected:
    inline Singleton(){}
    inline ~Singleton(){}

    private:
    static SINGLECLASS* s_instance;
    };

    template<class SINGLECLASS>
        SINGLECLASS* Singleton<SINGLECLASS>::s_instance = 0;

    template<class SINGLECLASS>
    SINGLECLASS& Singleton<SINGLECLASS>::instance()
    {
         if(s_instance==0)
            s_instance=new SINGLECLASS;
        return *s_instance;
    }

  • Well, I am unable to reproduce the problem, so no progress can be made on this issue.

    Note that there are expected deviations from the C++ standard in COFF ABI mode, particularly with respect to static locals in template member functions, but this problem is resolved in EABI (this issue is due to a fundamental limitation of COFF ABI).  This code should work just fine in EABI mode, regardless of whether inlining occurs.

  • I do not understand, why the "customer" has to "debug" a software for which he is paying. If I spend time reproducing the problem I expect at least a free licence for the fixed CCS version!

  • With rare exceptions, we must be able to reproduce the problem ourselves before we can do anything about it.  With the code and description you have given us so far, we are unable to do that.  We realize this means more work for you which you did not expect.  We're sorry about that.  But the simple fact is this: At this point, you are the only person who can advance this issue.  As much as we want to help, we cannot. 

    Thanks and regards,

    -George

  • Here is a simple example that reprocudes the mentioned problem.

    Kind regards

    Thomas

    2112.problem3.zip

  • I am able to reproduce a problem similar to what you've described, which I've entered as defect report SDSCM00043437.  What command line options are you using?  I'm guessing you are using optimization level 3.  Does the problem occur at optimization level 2?

    Which version of the compiler (not the CCS version) are you using?

  • Just with optimization level 3 and higher.

    I use compiler version TI v4.9.1

    regards

    Thomas