Compiler bug

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;
}

//--------------
 
G

Gary Chang

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.
--------------------
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top