Compiler bug

  • Thread starter Thread starter Guest
  • Start date Start date
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;
}

//--------------
 
Hi,

Do you have any more concerns on this issue, if so please feel free to post
here.


Thanks for your understanding!

Best regards,

Gary Chang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
--------------------
 
Back
Top