Hi all,

In attempting to use CSmartPtr (public/tier1/smartptr.h) along with
CRefCounted (public/tier1/refcount.h), I've encountered some unexpected
behavior. I assume that my usage is incorrect, as I'm basically looking for
something equivalent to boost/tr1's shared_ptr. The source for CSmartPtr and
CRefCounted are both pretty straightforward, but I see that
CRefCountServiceBase's constructor initializes m_iRefs to 1, and CSmartPtr's
operator=  further increments this ref count on assignment. This extra
reference leads to a memory leak, as the object isn't deleted by CSmartPtr's
destructor.

I put together a simple unit test to describe this behavior, listed below
with output. You'll notice that the second test case uses an object that
artificially decrements its reference count with Release() after
construction, allowing the test to pass. Any insight would be appreciated!

Casey "epicar" Bodley
Team Dystopia, Senior Programmer


//============================================================================
// SmartPtrTest.cpp
// Unit tests for CSmartPtr/CRefCounted
//============================================================================

// boost unit test includes
#define BOOST_TEST_MODULE "C++ Unit Tests for Source SDK's CSmartPtr and
CRefCounted"
#include <boost/test/unit_test.hpp>

// tier1 includes
#include <tier1/refcount.h>
#include <tier1/smartptr.h>


BOOST_AUTO_TEST_SUITE( TestSmartPtr )


class ObjectMock : public CRefCounted<>
{
public:
    typedef CSmartPtr<ObjectMock> Ptr;
    static Ptr Create() { return Ptr( new ObjectMock() ); }
    int PublicGetRefCount() const { return CRefCounted<>::GetRefCount(); }

private:
    ObjectMock() {}
    ~ObjectMock() {}
};

BOOST_AUTO_TEST_CASE( TestObjectMockRefCounts )
{
    ObjectMock::Ptr object = ObjectMock::Create();
    BOOST_CHECK_EQUAL( object->PublicGetRefCount(), 1 );
    BOOST_CHECK_EQUAL( object->Release(), 0 );
}


class ObjectMockWithRelease : public CRefCounted<>
{
public:
    typedef CSmartPtr<ObjectMockWithRelease> Ptr;
    static Ptr Create()
    {
        Ptr result( new ObjectMockWithRelease() );
        result->Release(); // decrement ref count after construction
        return result;
    }
    int PublicGetRefCount() const { return CRefCounted<>::GetRefCount(); }

private:
    ObjectMockWithRelease() {}
    ~ObjectMockWithRelease() {}
};

BOOST_AUTO_TEST_CASE( TestObjectMockWithReleaseRefCounts )
{
    ObjectMockWithRelease::Ptr object = ObjectMockWithRelease::Create();
    BOOST_CHECK_EQUAL( object->PublicGetRefCount(), 1 );
    BOOST_CHECK_EQUAL( object->Release(), 0 );
}


BOOST_AUTO_TEST_SUITE_END()

//============================================================================

Output:

1>Running unit tests for SmartPtr
1>Running 2 test cases...
1>e:/projects/test/smartptr/smartptrtest.cpp(33): error in
"TestObjectMockRefCounts": check object->PublicGetRefCount() == 1 failed [2
!= 1]
1>e:/projects/test/smartptr/smartptrtest.cpp(34): error in
"TestObjectMockRefCounts": check object->Release() == 0 failed [1 != 0]
_______________________________________________
To unsubscribe, edit your list preferences, or view the list archives, please 
visit:
http://list.valvesoftware.com/mailman/listinfo/hlcoders

Reply via email to