-6

i write a handle class using C++. But when i run my code, i met an error.

#pragma once

#include <iostream>
using std::cout;
using std::endl;

class BaseItem{
public:
    virtual BaseItem* clone()
    {
        return new BaseItem(*this);
    }
    virtual void sayHello()
    {
        cout<<"Hello, I am class BaseItem!"<<endl;
    }
};

class ChildItem:public BaseItem{
public:
    ChildItem* clone()
    {
        return new ChildItem(*this);
    }
    void sayHello(){
        cout<<"Hello, I am class ChildItem!"<<endl;
    }
};


template <typename T>
class Handle
{
public:
    Handle():baseItem(NULL), refCount(new size_t(0)) {}
    Handle(T& object):baseItem(object.clone()), refCount(new size_t(1)) {}

    Handle(const Handle<T>& other):baseItem(other.baseItem), refCount(new size_t(1)) {}

    Handle& operator= (const Handle<T>& other)
    {
        ++*other.refCount;
        dec_count();
        baseItem = other.baseItem;
        refCount = other.refCount;
        return *this;
    }

    const T* operator->() const {return baseItem;};
    const T& operator*() const {return *baseItem;};

    T* operator->() {return baseItem;};
    T& operator*() {return *baseItem;};

    virtual ~Handle(void)
    {
        dec_count();
    }
private:
    T *baseItem;
    std::size_t* refCount;
    void dec_count()
    {
        if (-- *refCount == 0 && baseItem != NULL)
        {
            delete baseItem;
            delete refCount;
        }
    }
};

This is the main function :

int _tmain(int argc, _TCHAR* argv[])
{
    BaseItem item1;
    ChildItem item2;

    vector<Handle<BaseItem> > vec;
    vec.push_back(Handle<BaseItem>(item1));
    vec.push_back(Handle<BaseItem>(item2));

    //for (vector<Handle<BaseItem> >::iterator iter = vec.begin();
    //  iter != vec.end(); iter++)
    //{
    //  
    //}
    return 0;
}

when i run the code, the code crashed. i have no idea to debug the code. This is the error: enter image description here

Andrejs Cainikovs
  • 27,428
  • 2
  • 75
  • 95
BlackMamba
  • 10,054
  • 7
  • 44
  • 67

3 Answers3

1

Your Handle's copy c-tor is invalid. It should be like this:

Handle(const Handle<T>& other)
  : baseItem(other.baseItem),
    refCount(other.refCount)
{
    ++*refCount;
}

http://ideone.com/DB7L9p

borisbn
  • 4,988
  • 25
  • 42
1

The problems I can see are:

  • The copy constructor should share and increase the reference count, rather than create a new one;
  • The base class needs a virtual destructor.

The first issue causes a double deletion after copying the handle into the vector. Both copies think they are the only reference to the object and hence both try to delete it. This is probably the cause of the crash.

After fixing those, your code appears to run correctly. If you still have problems, I suggest stepping through your failing test case with a debugger.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
0

Reference count should be a part of actual object rather than part of Handle. Handle should only increment & decrement the reference count & it should create once.

template <typename T>
class RefCounted
{
    public:
        std::size_t refCount;
};

class BaseItem : public RefCounted<BaseItem> {

So all classes which is being usable with Handle shall be derived from RefCounted.

template <typename T> class Handle
{
public:
    Handle():baseItem(NULL) {}
    Handle(T& object):baseItem(object.clone())) {++ other.refCount;}

    Handle(const Handle<T>& other):baseItem(other.baseItem) { ++ other.refCount; }

    Handle& operator= (const Handle<T>& other)
    {
        ++ other.refCount;
        baseItem = other.baseItem;
        return *this;
    }

    const T* operator->() const {return baseItem;};
    const T& operator*() const {return *baseItem;};

    T* operator->() {return baseItem;};
    T& operator*() {return *baseItem;};

    virtual ~Handle(void)
    {
        if (baseItem != NULL && -- (baseItem->refCount) == 0)
        {
            delete baseItem;
        }

    }
private:
    T *baseItem;

};

(Disclaimer: It is not a working code, just attempted to explain the concept)

If you are looking for better implementation, Refer http://trac.webkit.org/browser/trunk/Source/WTF/wtf/RefCounted.h

Arunprasad Rajkumar
  • 1,374
  • 1
  • 15
  • 31