G
Guest
In the below code, RefCntObject and RefCntCObject are automatic pointers to
non-const and const objects, respectively.
When the code is compiled with "cl a.cpp", all is fine, and the output is as
follows:
beforeFoo: 1
Addref: 2
foo: 2
Release: 1
afterFoo: 1
Release: 0
Once compiled with "cl /clr a.cpp", VC++ 7.1 (13.10.3077) produces
beforeFoo: 1
Addref: 2
Release: 1
foo: 1
Release: 0
afterFoo: 0
Release: -1
VC++ 8.0 (14.00.40904) produces
beforeFoo: 1
Addref: 2
foo: 3617544
Release: 3617543
afterFoo: 2
Release: 1
The problem goes away if either "#pragma unmanaged" or "Contsructor A" is
commented out.
//--------------
#include <windows.h>
#include <iostream>
using namespace std;
#pragma unmanaged
struct RefCntBase
{
RefCntBase()
{
m_lRefCnt = 1;
}
virtual ~RefCntBase() { }
void AddRef()
{
InterlockedIncrement( &m_lRefCnt );
cout << "Addref: " << m_lRefCnt << endl;
}
LONG Release()
{
LONG lResult = InterlockedDecrement( &m_lRefCnt );
cout << "Release: " << m_lRefCnt << endl;
if( lResult == 0 ) delete this;
return lResult;
}
LONG m_lRefCnt;
};
//---------------------------------------------------------------------------
template< class T >
class RefCntObject
{
public:
RefCntObject()
{
m_Ptr = NULL;
}
RefCntObject( bool isAddRef, T* ptr )
{
m_Ptr = ptr;
if( isAddRef ) AddRef();
}
RefCntObject( const RefCntObject& o )
{
m_Ptr = o.m_Ptr;
AddRef();
}
~RefCntObject()
{
Release();
}
void AddRef()
{
if( m_Ptr != NULL ) m_Ptr->AddRef();
}
void Release()
{
if( m_Ptr != NULL ) m_Ptr->Release();
}
T* GetPtr() { return m_Ptr; }
const T* GetPtr() const { return m_Ptr; }
T* operator->() { return m_Ptr; }
const T* operator->() const { return m_Ptr; }
protected:
T* m_Ptr;
};
//---------------------------------------------------------------------------
template< class T >
class RefCntCObject
{
public:
RefCntCObject()
{
m_Ptr = NULL;
}
RefCntCObject( bool isAddRef, const T* ptr )
{
m_Ptr = const_cast< T* >( ptr );
if( isAddRef ) AddRef();
}
//// Constructor A ////
#if 1
RefCntCObject( const RefCntCObject& o )
{
cout << "Constructor A" << endl;
m_Ptr = o.m_Ptr;
AddRef();
}
#endif
RefCntCObject( const RefCntObject< T >& o )
{
m_Ptr = const_cast< T* >( o.GetPtr() );
AddRef();
}
~RefCntCObject()
{
Release();
}
void AddRef()
{
if( m_Ptr != NULL ) m_Ptr->AddRef();
}
void Release()
{
if( m_Ptr != NULL ) m_Ptr->Release();
}
const T* GetPtr() const { return m_Ptr; }
const T* operator->() const { return m_Ptr; }
protected:
T* m_Ptr;
};
typedef RefCntObject< RefCntBase > O;
typedef RefCntCObject< RefCntBase > CO;
void foo( CO o )
{
cout << "foo: " << o->m_lRefCnt << endl;
}
#pragma managed
void main()
{
O o( false, new RefCntBase );
cout << "beforeFoo: " << o->m_lRefCnt << endl;
foo( o );
cout << "afterFoo: " << o->m_lRefCnt << endl;
}
//--------------
non-const and const objects, respectively.
When the code is compiled with "cl a.cpp", all is fine, and the output is as
follows:
beforeFoo: 1
Addref: 2
foo: 2
Release: 1
afterFoo: 1
Release: 0
Once compiled with "cl /clr a.cpp", VC++ 7.1 (13.10.3077) produces
beforeFoo: 1
Addref: 2
Release: 1
foo: 1
Release: 0
afterFoo: 0
Release: -1
VC++ 8.0 (14.00.40904) produces
beforeFoo: 1
Addref: 2
foo: 3617544
Release: 3617543
afterFoo: 2
Release: 1
The problem goes away if either "#pragma unmanaged" or "Contsructor A" is
commented out.
//--------------
#include <windows.h>
#include <iostream>
using namespace std;
#pragma unmanaged
struct RefCntBase
{
RefCntBase()
{
m_lRefCnt = 1;
}
virtual ~RefCntBase() { }
void AddRef()
{
InterlockedIncrement( &m_lRefCnt );
cout << "Addref: " << m_lRefCnt << endl;
}
LONG Release()
{
LONG lResult = InterlockedDecrement( &m_lRefCnt );
cout << "Release: " << m_lRefCnt << endl;
if( lResult == 0 ) delete this;
return lResult;
}
LONG m_lRefCnt;
};
//---------------------------------------------------------------------------
template< class T >
class RefCntObject
{
public:
RefCntObject()
{
m_Ptr = NULL;
}
RefCntObject( bool isAddRef, T* ptr )
{
m_Ptr = ptr;
if( isAddRef ) AddRef();
}
RefCntObject( const RefCntObject& o )
{
m_Ptr = o.m_Ptr;
AddRef();
}
~RefCntObject()
{
Release();
}
void AddRef()
{
if( m_Ptr != NULL ) m_Ptr->AddRef();
}
void Release()
{
if( m_Ptr != NULL ) m_Ptr->Release();
}
T* GetPtr() { return m_Ptr; }
const T* GetPtr() const { return m_Ptr; }
T* operator->() { return m_Ptr; }
const T* operator->() const { return m_Ptr; }
protected:
T* m_Ptr;
};
//---------------------------------------------------------------------------
template< class T >
class RefCntCObject
{
public:
RefCntCObject()
{
m_Ptr = NULL;
}
RefCntCObject( bool isAddRef, const T* ptr )
{
m_Ptr = const_cast< T* >( ptr );
if( isAddRef ) AddRef();
}
//// Constructor A ////
#if 1
RefCntCObject( const RefCntCObject& o )
{
cout << "Constructor A" << endl;
m_Ptr = o.m_Ptr;
AddRef();
}
#endif
RefCntCObject( const RefCntObject< T >& o )
{
m_Ptr = const_cast< T* >( o.GetPtr() );
AddRef();
}
~RefCntCObject()
{
Release();
}
void AddRef()
{
if( m_Ptr != NULL ) m_Ptr->AddRef();
}
void Release()
{
if( m_Ptr != NULL ) m_Ptr->Release();
}
const T* GetPtr() const { return m_Ptr; }
const T* operator->() const { return m_Ptr; }
protected:
T* m_Ptr;
};
typedef RefCntObject< RefCntBase > O;
typedef RefCntCObject< RefCntBase > CO;
void foo( CO o )
{
cout << "foo: " << o->m_lRefCnt << endl;
}
#pragma managed
void main()
{
O o( false, new RefCntBase );
cout << "beforeFoo: " << o->m_lRefCnt << endl;
foo( o );
cout << "afterFoo: " << o->m_lRefCnt << endl;
}
//--------------