Global Variables

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
ColdFusion
Posts: 5
Joined: Fri May 14, 2010 10:30 pm

Global Variables

Post by ColdFusion »

I Would like to keep my variables accessible from everywere in all files so i made my device namespace etc global. but when calling device->run() outside of loadmenu. i get a unhandled exception

Code: Select all

void loadmenu()	
{
		IGUISkin* skin = env->getSkin();
        IGUIFont* font = env->getFont("../../media/fonthaettenschweiler.bmp");
        if (font)
                skin->setFont(font);

        skin->setFont(env->getBuiltInFont(), EGDF_TOOLTIP);
		env->addButton(rect<s32>(10,variable::getvar_int("ResolutionY") - 30,110,variable::getvar_int("ResolutionY") - 10), 0, GUI_ID_QUIT_BUTTON,
                        L"Quit", L"Exits Program");
        env->addButton(rect<s32>(10,variable::getvar_int("ResolutionY") - 60,110,variable::getvar_int("ResolutionY") - 40), 0, GUI_ID_START_BUTTON,
                        L"Start", L"Start Game");

        // Store the appropriate data in a context structure.
        SAppContext context;
        context.device = device;
        context.counter = 0;

        // Then create the event receiver, giving it that context structure.
        //MyEventReceiver receiver(context);

        // And tell the device to use our custom event receiver.
        //device->setEventReceiver(&receiver);
}
void menuloop()
{
	if(device->run())
	{
		driver->beginScene(true, true, SColor(0,200,200,200));
		env->drawAll();
		smgr->drawAll();
		driver->endScene();
	}
}
Thank you for reading
greenya
Posts: 1012
Joined: Sun Jan 21, 2007 1:46 pm
Location: Ukraine
Contact:

Post by greenya »

Check if you do not define another "device" variable by mistake inside the method, because if you do, when you assign "device" you do it for local variable (not global).

Code you posted not shows importance parts, where you do:
- define "device" variable;
- assign value to "device" variable;
- call sequence of menuloop(), void loadmenu() and the function where you assign "device";

P.S.: and show your main() if not long.
slavik262
Posts: 753
Joined: Sun Nov 22, 2009 9:25 pm
Location: Wisconsin, USA

Post by slavik262 »

From a general programming perspective, it's often best to pass variables and references through function calls (or if a class needs a variable/reference, pass it in in the constructor). Generally speaking, global variables are bad.

Also, from StackOverflow,
The problem with global variables is that since every function has access to these, it becomes increasingly hard to figure out which functions actually read and write these variables.

To understand how the application works, you pretty much have to take into account every function which modifies the global state. That can be done, but as the application grows it will get harder to the point of being virtually impossible (or at least a complete waste of time).

If you don't rely on global variables, you can pass state around between different functions as needed. That way you stand a much better chance of understanding what each function does, as you don't need to take the global state into account.
Basically, it's the problem you've run into: Since your device is global, knowing its state can be difficult. I'm not saying to "never make a device global ever", but IMO there's better ways to do it (pass the device pointer into your loadmenu function, or create an object that contains loadmenu that takes the device pointer as a constructor).
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

Code: Select all

// Then create the event receiver, giving it that context structure. 
MyEventReceiver receiver(context); 

// And tell the device to use our custom event receiver. 
device->setEventReceiver(&receiver); 
The above code is the problem. You create a MyEventReceiver on the stack, and you pass a pointer to it to your device. When the function loadmenu() returns, the MyEventReceiver is destroyed, but the device still has a pointer to it. At some point later, the device tries to send events to your event receiver. BOOM!

The easy solution is to allocate the event receiver on the heap so that it doesn't get destroyed until you want it to. The issue with this is that you need to be sure to deallocate the event receiver manually when you are done with it...

Code: Select all

IEventReceiver* r = device->getEventReceiver();
device->setEventReceiver(newReceiverOrNull);
delete r;
Travis
ColdFusion
Posts: 5
Joined: Fri May 14, 2010 10:30 pm

Post by ColdFusion »

Thank you vitek

Also i tought about moving the device, scenenode, gui arround but i tought passing arround 5 pointers to every function would not be the best idea
CuteAlien
Admin
Posts: 9935
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Post by CuteAlien »

ColdFusion wrote: Also i tought about moving the device, scenenode, gui arround but i tought passing arround 5 pointers to every function would not be the best idea
2 ways around that which both involve structs/classes. First you can put several pointers into one class and just pass that to functions. For example if you pass around the Irrlicht device pointer, then you also have access from that on to all the other Irrlicht classes like guienvironment, videodriver, filesystem, etc. because they are all part of the device.

The other solution is that you initialize your target class once with certain pointers (for example in the constructor) and save those in that class. From there on you can use them in all member-functions of that class so you don't have to pass it always.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Post Reply