views:

585

answers:

6

Hi,

I'm using static initialisation to ease the process of registering some classes with a factory in C++. Unfortunately, I think the compiler is optimising out the 'unused' objects which are meant to do the useful work in their constructors. Is there any way to tell the compiler not to optimise out a global variable?

class SomeClass {
    public:
        SomeClass() {
            /* do something useful */
        }
};

SomeClass instance;

My breakpoint in SomeClass's constructor doesn't get hit. In my actual code, SomeClass is in a header file and instance is in a source file, more or less alone.

EDIT: As guessed by KJAWolf, this code is actually compiled into a static lib, not the executable. Its purpose is to register some types also provided by the static lib with a static list of types and their creators, for a factory to then read from on construction. Since these types are provided with the lib, adding this code to the executable is undesirable.

Also I discovered that by moving the code to another source file that contains other existing code, it works fine. It seems that having a file purely consisting of these global objects is what's causing the problem. It's as if that translation unit was entirely ignored.

+4  A: 

The compiler should never optimize away such globals - if it does that, it is simply broken.

Pavel Minaev
If the compiler can detect no use of the global, it can omit them. GCC (G++ in this context) can and does omit some variables - for example, the old 'embed a version in the object file' tricks do not work with modern GCC - the file static value is detected as unused and optimized out of the object file.
Jonathan Leffler
file static != global
anon
If they have a cnstructor then there is a potential side affect from using the constructor. As gcc does not do cross function analysis it would never be able to detect the potential of a side affect and thus would not be allowed to remove it.
Martin York
What Martin said. If constructor has an observable side effect, it cannot be removed regardless of whether it's static or not. Also, I'm not sure I understand your remark, Neil - IIRC, the C spec doesn't define "global" in any way, so its definition is open, and "global is anything that's not local or member" is a fairly reasonable one (though not the only one, obviously).
Pavel Minaev
@Pavel Something like static int x; obviously cannot be "global" and could definitely be elided by the compiler. My point was that things that might be global (i.e. linked to by other compilation units) cannot be elided by the compiler, constructor or no, because the compiler cannot know if they are going to be linked to.
anon
It's still a global as far as I'm concerned (it's visible by all functions in the compilation unit, so what is it then?), but arguing term definitions is pointless. However, even for a "static global", if its constructor has _observable side effects_, the compiler cannot legally elide it.
Pavel Minaev
Well, of course it isn't so visible (depending on where it is defined), but we seem to be at cross purposes. I've nowhere said that that I disagree with the point about constructor elidation
anon
+6  A: 

The compiler is not allowed to optimiza away global objects.
Even if they are never used.

Somthing else is happening in your code.
Now if you built a static library with your global object and that global object is not referenced from the executable it will not be pulled into the executable by the linker.

Martin York
I've upvoted this because I think it's the only answer that nails the real problem; As the questioner says "It seems that having a file purely consisting of these global objects is what's causing the problem. It's as if that translation unit was entirely ignored". The translation unit is being ignored in the sense that it is being omitted by the linker because it's in a library. If an object is in a library and isn't called by anything in the app, it's omitted, that's the whole idea of libaries!
Bill Forster
Ditto, that hit the nail on the head. I upvoted Pavel's answer too since he also got it right :)
Ben Hymers
+2  A: 

To build off of Arthur Ulfeldt, volatile tells the compiler that this variable can change outside of the knowledge of the compiler. I've used it for put a statement to allow the debugger to set a breakpoint. It's also useful for hardware registers that can change based on the environment or that need a special sequence. i.e. Serial Port receive register and certain watchdog registers.

Robert
No, it simply tells the compiler that it must not cache a previously read value of the variable.
anon
It is useful for multithreading :)
Partial
A: 

you could use

#pragma optimize off
int globalVar
#pragma optimize on

but I dunno if that only works in Visual Studio ( http://msdn.microsoft.com/en-us/library/chh3fb0k(VS.80).aspx ).

You could also tell the compiler to not optimize at all, especially if you're debugging...

atk
This is not compatible with every IDE/compilers.
Partial
A: 

Are you using gcc with gdb? There was a problem in the past where gdb could not accurately set breakpoints in constructors.

Also, are you using an optimization level which allows the compiler to inline methods in the class definition.

Juan
A: 

How about using the keyword volatile? It will prevent the compiler from too much optimization.

Partial