-1

I've been some research on a bug i'm facing right now, it turns out that C++ initializes classes before runtime (and calling the main function). My program however, is an opengl program which requires certain things to be set up before anything else is done.... Is there any way to fix this? The problem is simple, but here's some pseudo/c++ code anyways:

class shader
{
    shader() { /* constructor... DEPENDS ON GL SET UP! But called first!*/ }
} 

// global/static shaders
shader geometry;
shader lighting;

int main()
{
    glewInit(); // initialize opengl
}

Edit: Added some more info based off comments. Yes, my shader classes are static and they are the problem. The only solution is to make these static classes into pointers and allocate them after main's initialization is finished? Or is there a way to delay initialization?

callyalater
  • 3,102
  • 8
  • 20
  • 27
Jas
  • 850
  • 7
  • 21
  • That code alone won't call a constructor. You presumably also have an object of type `shader` with static storage duration. – aschepler Feb 16 '16 at 21:53
  • Yes, all my shaders are static. So they are being constructed before my main function? – Jas Feb 16 '16 at 21:56
  • 3
    Pseudo code won't help. Please provide a [MCVE](http://stackoverflow.com/help/mcve) to demonstrate. It sounds like you're using statics, which are initialised before you enter `main`. – paddy Feb 16 '16 at 21:56
  • http://stackoverflow.com/questions/15235526/the-static-keyword-and-its-various-uses-in-c/15235626#15235626 – πάντα ῥεῖ Feb 16 '16 at 22:08
  • https://isocpp.org/wiki/faq/ctors#static-init-order-on-first-use is one possibility. – user253751 Feb 16 '16 at 22:11
  • And I don't see why this entirely reasonable question is downvoted. #paddy The OP appears to know what the problem is, and be asking how to fix it. – user253751 Feb 16 '16 at 22:11

2 Answers2

2

You should stop putting code in the constructors of global variables which requires glewInit to have been called.

In fact it is a good idea to avoid having global variables whose constructors or destructors do anything, because the order that global variables are initialized is not clear . Having global destructors makes your shutdown sequence more difficult too.

If you want to use a global variable because it's too annoying to use a local variable to main() and pass it around everywhere, then you will need to make sure that global variable does not get initialized until later. One way to do this is to put it in a function:

shader &geometry()
{
    static shader g;
    return g;
}

and in your header file , shader &geometry(); , and make sure to not call this anywhere from other global variables! The static variable inside a function is not initialized until the first call to the function. (Warning: you still can't control the destruction order this way - you won't be able to cleanly destroy this shader and then un-initialize GL)

Another way is to use a smart pointer:

std::unique_ptr<shader> p_geometry;

int main()
{
    glewInit();

    p_geometry = std::make_unique<shader>();

    // use *p_geometry... 

    // If you want to shut down tidily
    p_geometry.reset(nullptr);        
}
M.M
  • 138,810
  • 21
  • 208
  • 365
1

Objects declared outside of any function or class are placed in global scope. Such objects are constructed before main is executed. That's why your shader objects are constructed before OGL is initialized.

This is probably what you need to do:

int main()
{    
    glewInit(); // initalize opengl

    shader geometry;
    shader lighting;
}

Simply moving shader objects into local scope of the main function will make sure they are initialized when you want them to - after the glewInit() call.

Violet Giraffe
  • 32,368
  • 48
  • 194
  • 335