Sign in to follow this  
Teenage Death Boy

Can't use an STL Map in a method? [Solved]

Recommended Posts

Ok so I was having some problems with my STL map that I am using in my texture manager. So I whipped up a quick test. As part of my texture manager class, I have std::map<int, int> test; Yes I realise this is pointless, it is only a test. Created a quick test function void TextureManager::testfunc() { test[5] = 25; } But this crashes somewhere in the STL code. The weird thing is, it's fine if I try the same statement in the constructor. Is there something painfully obvious I have overlooked, or does anyone know a reason that could be causing this? [Edited by - Teenage Death Boy on July 1, 2005 10:25:55 AM]

Share this post


Link to post
Share on other sites
Boku San    428
Well, I've never tried this before, to be honest. But maybe the address can't be resolved if it's called outside of a constructor? I'm not sure, but isn't this a similar case to using a const member (which can only be initialized in a constructor's initializer list, afaik)?

Just a guess, probably get you started thinking...or something.

Share this post


Link to post
Share on other sites
Deyja    920
There is no reason the code he posted would fail. Until he posts it in context, it's just guesswork.

Share this post


Link to post
Share on other sites
s_p_oneil    443
This could also happen if he's using MS Visual C++ 6.0 and he's making calls from one module (DLL or EXE) to another. If his constructor is inlined and this method is not, it would exhibit behavior like this.

Share this post


Link to post
Share on other sites
	
class gameTextureManager
{
private:
SINGLETON_DECLARE(gameTextureManager);
std::vector<int> test;
public:
SINGLETON_METHODS(gameTextureManager);

void push();
};






This was the quick test class I wrote up. The class is made a singleton, using some source that a member of the forums gave me (roots from The Hero of Allacrost, source available in the CVS).

For quick reference:

/******************************************************************************
SINGLETON macros - used for turning a class into a singleton class

The following three macros turn a normal class into a singleton class. To create a singleton class, perform the following steps.

1) The class' header file must #include "utils.h"
2) Place SINGLETON_DECLARE(class_name) in the class' private section.
3) Place SINGLETON_METHODS(class_name) in the class' public section.
4) Place SINGLETON_INITIALIZE(class_name) at the top of the class' source file.
5) *REQUIRED* Implement the class' constructor and destructor (even if it does nothing).

After performing these steps, your class with have 3 functions publicly avaiable to it:

- _Create(): creates the new singleton and returns a pointer to the class object
- _Destroy(): destroys the singleton class
- _GetRefCount(): returns a pointer to the class object

Notes and Usage:

1) The constructor and destructor *MUST* be defined! If you do not implement them, then you will get a compilation error like:
> In function `SINGLETON::_Create()': undefined reference to `SINGLETON::SINGLETON[in-charge]()

2) You can not create or delete instances of this class normally. Ie, calling the constructor, copy constructor, copy assignment operator, destructor, new/new[], or delete/delete[] operators will result in a compilation error. Use the _Create(), _Destroy(), and _GetReference() functions instead.

3) The only place _Create() and _Destroy() should usually be called are in loader.cpp. But if a different section of code detects a fatal error and needs to exit the game, _Destroy() should be called for *all* Singletons.

4) FYI: _Create() and _Destroy() can be called multiple times without any problem. The only time you need to worry is if _Destroy() is called and then a part of the code tries to reference a pointer to the old singleton. Thus...

>>> ONLY CALL _Destroy() WHEN YOU ARE EXITING OR ABORTING THE ENTIRE APPLICATION!!! <<<

5) You can get a class object pointer like this: 'MYCLASS *test = MYCLASS::_GetReference();'
*****************************************************************************/

// Put in the private sector of the class definition
#define SINGLETON_DECLARE(class_name)
static class_name *_ref; class_name(); ~class_name(); class_name(const class_name&); class_name& operator=(const class_name&);

// Put in the public sector of the class definition
#define SINGLETON_METHODS(class_name) static class_name* _Create() { if (_ref == NULL) { _ref = new class_name(); } return _ref; } static void _Destroy() { if (_ref != 0) { delete _ref; ref = NULL; } } static class_name* _GetReference() { return _ref; }

// Put in the class' source file
#define SINGLETON_INITIALIZE(class_name) class_name* class_name::_ref = NULL;




In my main .cpp it is correctly set up with

gameTextureManager *textureManager = gameTextureManager::_Create();

and

gameTextureManager::_Destroy();

In the implementation of the class, I have also used

SINGLETON_INITIALIZE(gameTextureManager);

as is required.



gameTextureManager::gameTextureManager()
{
test.push_back(12);
}

gameTextureManager::~gameTextureManager() { }

void gameTextureManager::push()
{
test.push_back(15);
}






The constructor can do it no problem, but I can't do it using the push method.

Share this post


Link to post
Share on other sites
Andrew Russell    1394
OK, that code *should* be fine. I suggest to you that your problem could be that your "this" pointer is corrupt. In other words, push() is being called on an invalid object.
gameTextureManager* t = reinterpret_cast<gameTextureManager*>(rand());
t->push();
The above code is an extreme example of what could cause it.

Share this post


Link to post
Share on other sites
Quote:
Original post by Andrew Russell
OK, that code *should* be fine. I suggest to you that your problem could be that your "this" pointer is corrupt. In other words, push() is being called on an invalid object.
gameTextureManager* t = reinterpret_cast<gameTextureManager*>(rand());
t->push();
The above code is an extreme example of what could cause it.



Well you were partially right. I was being an idiot. I _Create'd my video manager before my texture manager, and tried to use _GetReference before the texture manager had properly been constructed. Ooops ^_^ (but thank you everyone for your help)

Share this post


Link to post
Share on other sites
Andrew Russell    1394
Quote:
Original post by Teenage Death Boy
Quote:
Original post by Andrew Russell
OK, that code *should* be fine. I suggest to you that your problem could be that your "this" pointer is corrupt. In other words, push() is being called on an invalid object.
gameTextureManager* t = reinterpret_cast<gameTextureManager*>(rand());
t->push();
The above code is an extreme example of what could cause it.



Well you were partially right. I was being an idiot. I _Create'd my video manager before my texture manager, and tried to use _GetReference before the texture manager had properly been constructed. Ooops ^_^ (but thank you everyone for your help)


Here's a tip for you then. I assume that your singleton has a static member pointer. You need to initialize that to NULL staticly. Then in your GetReference() function, you should drop in an assert to check it.

example:
class Foo
{
static Foo* singleton;
public:
Foo() {assert(!singleton); singleton = this;}
~Foo() {assert(singleton); singleton = NULL;}

static Foo& GetReference()
{
assert(singleton);
return (*singleton);
}
};

Foo* Foo::singleton = NULL;



Suggest you use code similar to that for all your singletons. Then you will get error messages if you screw up your initialization.

The code above gives these errors (in order) - if you try and make more than one, if you try and delete when you don't have one, and when you try and get a reference when you don't have one.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this