Thread: dynamic allocation class

  1. #1
    Registered User
    Join Date
    May 2004
    Posts
    73

    dynamic allocation class

    Hey everyone

    Here's my problem: In my last rewrite of my game, there were memory leaks everywhere. In this rewrite, I don't want that to happen. If it does, tracking them down takes a lot of time.

    So here's my objective: Make a class that can track memory leaks.

    So I'm thinking, I'll just make a templated class that will tell me if the data wasn't freed by the time the destructor fires. Here's what I have so far:

    Code:
    template<class Type>
    class vDynamicData
    {
    private:
    	Type* Data;
    	char* Name;
    
    public:
    	vDynamicData( char* _Name );
    	~vDynamicData();
    	void Allocate();
    	void Free();
    	Type* Get();
    	operator Type*();
    };
    
    template<class Type>
    vDynamicData<Type>::vDynamicData( char* _Name )
    {
    	Data = NULL;
    	Name = _Name;
    }
    
    template<class Type>
    vDynamicData<Type>::~vDynamicData()
    {
    	if( Data )
    	{
    		cout << "Unfreed: " << Name << endl;
    	}
    }
    
    template<class Type>
    void vDynamicData<Type>::Allocate()
    {
    	Data = new Type;
    }
    
    template<class Type>
    void vDynamicData<Type>::Free()
    {
    	delete Data;
    	Data = NULL;
    }
    
    template<class Type>
    vDynamicData<Type>::operator Type*()
    {
    	return Data;
    }
    The last function, the operator Type*() one, is to allow the use of dereferencing and the -> operator. Dereferencing works beautifully. The -> operator doesn't. So I looked on google, it turns out overloading the -> operator isn't allowed. But I'm not overloading it, I'm doing a typecasting... thing. (Not sure how to put that in words, lol.)

    So how can I get the -> operator to work?

    Here's the code where I test it out:

    Code:
    struct MyType
    {
    	int A;
    	bool B;
    	char C;
    };
    
    int main()
    {
    	vDynamicData<MyType> Num( "Test MyType" );
    	Num.Allocate();
    
    	Num->A = 3;
    	Num->B = true;
    	Num->C = '@';
    
    	cout << Num->A << Num->B << Num->C << endl;
    
    	Num.Free();
    
    	return 0;
    }
    and here's the errors I get:
    c:\Documents and Settings\Evan Ovadia\My Documents\Visual Studio Projects\vDynamics\Main.cpp(67): error C2227: left of '->A' must point to class/struct/union
    c:\Documents and Settings\Evan Ovadia\My Documents\Visual Studio Projects\vDynamics\Main.cpp(71): error C2227: left of '->A' must point to class/struct/union
    c:\Documents and Settings\Evan Ovadia\My Documents\Visual Studio Projects\vDynamics\Main.cpp(68): error C2227: left of '->B' must point to class/struct/union
    c:\Documents and Settings\Evan Ovadia\My Documents\Visual Studio Projects\vDynamics\Main.cpp(71): error C2227: left of '->B' must point to class/struct/union
    c:\Documents and Settings\Evan Ovadia\My Documents\Visual Studio Projects\vDynamics\Main.cpp(69): error C2227: left of '->C' must point to class/struct/union
    c:\Documents and Settings\Evan Ovadia\My Documents\Visual Studio Projects\vDynamics\Main.cpp(71): error C2227: left of '->C' must point to class/struct/union
    c:\Documents and Settings\Evan Ovadia\My Documents\Visual Studio Projects\vDynamics\Main.cpp(67): error C2819: type 'vDynamicData<Type>' does not have an overloaded member 'operator ->'
    with
    [
    Type=MyType
    ]
    c:\Documents and Settings\Evan Ovadia\My Documents\Visual Studio Projects\vDynamics\Main.cpp(68): error C2819: type 'vDynamicData<Type>' does not have an overloaded member 'operator ->'
    with
    [
    Type=MyType
    ]
    c:\Documents and Settings\Evan Ovadia\My Documents\Visual Studio Projects\vDynamics\Main.cpp(69): error C2819: type 'vDynamicData<Type>' does not have an overloaded member 'operator ->'
    with
    [
    Type=MyType
    ]
    c:\Documents and Settings\Evan Ovadia\My Documents\Visual Studio Projects\vDynamics\Main.cpp(71): error C2819: type 'vDynamicData<Type>' does not have an overloaded member 'operator ->'
    with
    [
    Type=MyType
    ]
    c:\Documents and Settings\Evan Ovadia\My Documents\Visual Studio Projects\vDynamics\Main.cpp(71): error C2819: type 'vDynamicData<Type>' does not have an overloaded member 'operator ->'
    with
    [
    Type=MyType
    ]
    c:\Documents and Settings\Evan Ovadia\My Documents\Visual Studio Projects\vDynamics\Main.cpp(71): error C2819: type 'vDynamicData<Type>' does not have an overloaded member 'operator ->'
    with
    [
    Type=MyType
    ]

  2. #2
    Registered User The Dog's Avatar
    Join Date
    May 2002
    Location
    Cape Town
    Posts
    788
    See if it works by assigning Num to a MyType pointer.

    MyType* ptr = Num;
    ptr->A = 3;
    ptr->B = true;
    ptr->C = '@';

    It might be the fact the operator function works on one side only, if you know what I mean.
    Either as an L-Value or a R-Value.

    I think!!

  3. #3
    Registered User
    Join Date
    May 2004
    Posts
    73
    You sure I can't do it on the left side?

    Another one of the goals of this class is to be able to switch out all occurrences of vDynamicData<Type> with Type* (of course, there's still a few thigs I need to do like replace Allocate() with new and Free() with delete). Making a copy of the pointer wouldnt make sense once everything's switched.

  4. #4
    Registered User The Dog's Avatar
    Join Date
    May 2002
    Location
    Cape Town
    Posts
    788
    I see what you're saying. I'm sure there's a way, I think it's just the syntax of the operator function that needs to change.

  5. #5
    Registered User
    Join Date
    May 2004
    Posts
    73
    After a bit of testing, I found that this way works:

    Code:
    ( (MyType*)Num )->A = 3;
    ...so l-value typecasting is still allowed...

    ...but that whole thing is so much weirder than Num->A, so back to square one.

  6. #6
    carry on JaWiB's Avatar
    Join Date
    Feb 2003
    Location
    Seattle, WA
    Posts
    1,972
    You could just do (*num).A

    Another thing you might want to consider is the std::auto_ptr, which I believe does essentially what you want.

    here's a short example:
    Code:
    #include <memory>
    #include <iostream>
    
    void SomeFunc(std::auto_ptr<int> A)
    {
    std::cout<<*A<<std::endl;
    
    }
    
    std::auto_ptr<int> AnotherFunc()
    {
    std::auto_ptr<int> newptr(new int);
    *newptr = 10;
      return newptr;
    }
    
    int main()
    {
    std::auto_ptr<int> A(new int);
    std::auto_ptr<int> B(new int);
    
    *A = 5;
    *B = 6;
    
    SomeFunc(A);
    // std::cout<<*A; //error, SomeFunc gained ownership of A; A is a null pointer
    
    std::cout<<*B<<std::endl;
    B = AnotherFunc(); //deallocate B, assign a new pointer to it
    std::cout<<*B<<std::endl;
    
    A = B;
    std::cout<<*A;
    // std::cout<<*B; //error, A has ownership; B is null
    
    //A destructor cleans up
    }
    One thing to keep in mind if using auto_ptrs is that no two auto_ptrs can share the same object, so anytime you pass one to a function you can't use it unless you assign it a new pointer.
    "Think not but that I know these things; or think
    I know them not: not therefore am I short
    Of knowing what I ought."
    -John Milton, Paradise Regained (1671)

    "Work hard and it might happen."
    -XSquared

  7. #7
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Unless you want to just try to do this for fun and learning, an even better alternative might be boost::shared_ptr. It will be part of the next standard, and is already part of TR1 which is like an early draft of some things that will be standardized.

    It is pretty easy to download and use, and it handles deleting the memory for you. You can even look through the code to see how they implemented that smart pointer (overloading operator-> and stuff).

    As far as operator->, you can overload it, how did you try?

  8. #8
    Registered User
    Join Date
    May 2004
    Posts
    73
    I didn't really know where to start. I tried something like this:

    Code:
    void* operator -> ( Type::*Member )
    {
       return Data->Member;
    }
    ...but it was just a random guess. I didn't really expect it to work.

    I looked at that auto_ptr thing, and I saw that they did in fact overload the -> operator.

    Code:
    	_Ty *operator->() const _THROW0()
    		{	// return pointer to class object
    		return (&**this);
    		}
    _Ty was defined as void, _THROW0() was defined to throw, so it came out as this:

    Code:
    void* operator -> () const throw
    {
    	return (&**this);
    }
    And then I thought, "why is there a &* in there? that's kinda dumb..." so I took that out...

    Code:
    void* operator -> () const throw
    {
    	return *this;
    }
    and I tried to compile that, but it won't because dereferencing "this" will return a reference, not a void*.

    Anyway, I don't get how they did it. And I can't use any of those classes provided to me because I need to make my own.

    How did they overload the -> operator?

  9. #9
    Registered User
    Join Date
    May 2004
    Posts
    73
    Ah, as it turns out _Ty wasn't defined as void. It was actually defined in every single class in every single header EVERYWHERE...

    _Ty is basically Type.

    Code:
    Type* operator -> ()
    {
    	return Data;
    }
    I got it down to that, and it works ^^

    But I don't know why. In that function, -> is unary. But when I use it like Num->A, it's binary. What's going on?

  10. #10
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    It isn't binary, it is unary. It is like saying (Num.operator->())->A, where it calls the function first and then continues on with the rest of the statement. It's a little awkward but now that you know how it works you can see that it is easier to implement than the other way.

    BTW, I forgot to mention this before, but underscores followed by capital letters are reserved identifiers, so you should consider changing _Name to something else (e.g. Name_).
    Last edited by Daved; 08-14-2005 at 12:23 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. matrix class
    By shuo in forum C++ Programming
    Replies: 2
    Last Post: 07-13-2007, 01:03 AM
  2. Message class ** Need help befor 12am tonight**
    By TransformedBG in forum C++ Programming
    Replies: 1
    Last Post: 11-29-2006, 11:03 PM
  3. Dynamic allocation (I thought it would crash)
    By Baaaah! in forum C Programming
    Replies: 16
    Last Post: 11-30-2005, 05:10 PM
  4. operator overloading and dynamic memory program
    By jlmac2001 in forum C++ Programming
    Replies: 3
    Last Post: 04-06-2003, 11:51 PM