Jump to content
  • Advertisement
Sign in to follow this  
silverphyre673

Very, very odd smart pointer issue with magically changing data

This topic is 4394 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

So I wrote a simple reference-counted smart pointer system to work with my simple game engine. It's having an issue, though. See here: (C++, as you can see)
class SimpleRefCountObj
{
    int ref;
    SimpleRefCountObj():ref(0){}
    
    void AddRef(){++ref;}
    void Release(){--ref;} //Some other things actually go on in these
                           //two functions relating to garbage collection
};

template <class T>
class SmartPtr
{
    T * object;
    public:
    SmartPtr():object(0){}

    SmartPtr & operator = (T * obj)
    {
        if (object) object->Release(); //Removes a reference
        object = obj;
        if (object) object->AddRef(); //Adds a reference.
    }
};

class FooBar : public Singleton<FooBar>
{
    public:
    SmartPtr<SimpleRefCountObj> objPtr;
};

void foo()
{
    new FooBar; //Allocates memory to a  static pointer to FooBar, which can be         
                //accessed via FooBar::Instance()   
}

Here's the issue: as determined via my exquisite error logging system, during the "new FooBar" statement in foo(), SmartPtr::SmartPtr() is getting called, as you would expect. This should set objPtr.object to the value of zero. This happens, when we are inside SmartPtr::SmartPtr(). However, immediately after "new FooBar," as in logging in the very next statement, the value of FooBar::Instance().objPtr is not equal to 0 - it is equal to 253. I checked the sizeof(FooBar::Instance()), which returns a reference to the static FooBar object. This returns the value 4. If I add an "int" member variable to FooBar, it changes the size to 8. When I comment out the member variable objPtr (leaving FooBar with no member variables), the sizeof(FooBar::Instance()) returns 1. I would expect it to be zero (right?) Why would sizeof(SmartPtr) be equal to three? It seems like objPtr.object's last byte is one further out of bounds than it should be. Logging the value of objPtr.object says that after the call to "new FooBar," it has the value of 253, which fits into a byte. How could the memory be getting, I don't know, misaligned like this? It's all very confusing to me. Thanks for any help, and I can post any more code you need (the above is just an example). Thanks again!

Share this post


Link to post
Share on other sites
Advertisement
First things first: please tell me there's a very good reason you're not using one of boost's existing smart-pointer classes. They're extremely potent, thoroughly tested and debugged, and already written for free.


Is this code running in vacuum, or as part of another block of code? My first suspicion here is that you've got a memory corruption bug someplace. Second suspicion is that something funky is going on with your Singleton stuff; what happens if you try this on a totally separate test class? Can you post the Singleton class code?


As to the results of sizeof() - no object can have a 0 size. This is to guarantee that if you new several "empty" objects, they at least get unique pointer addresses, even though they use no memory technically.

Lastly, memory in classes/structures doesn't simply get misaligned (unless you're mucking around pretty hardcore with __declspec(align) and the like) - if there is really a phantom corruption going on, it's your bug, somewhere or another.

Share this post


Link to post
Share on other sites
Most of my code is from the Enginuity series, and somewhat modified. I think I'm just going to swap in boost for the code they use, though - I have never gone wrong with boost :)

Share this post


Link to post
Share on other sites
Without thinking too much about your actual problem, I notice that your operator=() removes a reference to the old object before adding a reference to the new one. If object == obj, this can be bad.

Also, add a copy constructor to SmartPtr.

Share this post


Link to post
Share on other sites
Quote:
Original post by silverphyre673
I checked the sizeof(FooBar::Instance()), which returns a reference to the static FooBar object. This returns the value 4. If I add an "int" member variable to FooBar, it changes the size to 8. When I comment out the member variable objPtr (leaving FooBar with no member variables), the sizeof(FooBar::Instance()) returns 1. I would expect it to be zero (right?) Why would sizeof(SmartPtr) be equal to three?
Wrong!
The standard guarantees that structures are never zero bytes in size, or something to that effect. I don't recall the exact wording. It prevents instances from sharing the same address anyway.

Don't roll your own smart pointer, it will never be as good. For instance, you're not returning anything from your = operator, also it should ideally be returning a const-reference. The list goes on...

Share this post


Link to post
Share on other sites
And just for the record, I remember Superpig talking about some bugs in the Enguinity code. Can't remember the exact details, but there was something about it trying to delete objects allocated on the stack, and a few other issues.

And yeah, like said above, a struct/class always has a minimum size of 1.
And like also said above, just use boost... [lol]

Share this post


Link to post
Share on other sites
I believe that a class with no members can be treated as size zero by the compiler when inheriting from it.

Share this post


Link to post
Share on other sites
Quote:
Original post by rip-off
I believe that a class with no members can be treated as size zero by the compiler when inheriting from it.


It can, this is referred to empty base member optimisation. However, no object can have a 0 size. Instantiating a class deriving from N other classes is still only instantiating a single object, so that single object can still have a size of 1 if itself and all of it's bases are empty.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!