By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,594 Members | 3,552 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,594 IT Pros & Developers. It's quick & easy.

MSVC 2003: ctor-try-block error: possible compiler bug

P: n/a
This message was originally posted to comp.lang.c++.moderated
----------------------------------------------------------------------------------------------

Hi!

I face a problem in my production code. I could deduce this problem to
program shown below. It seems, that try-block in constructor doesnt
work as it should (compared to case where no try block exists at all).
I tested this small program on my MSVC .NET Pro 2003 (and separately on
PC with MSVC2003 SP1 installed). In both cases I experienced the same
behaviour - access violation. Please see comment inside the program
body. To get this sample work - just comment out try block in ctor.

Have anyone faced such behaviour before? Is there known workarounds?
Thanks.
----
// ref_count.cpp : ctor try block invalid behaviour test

// if ctor uses try block (X::X), program crashes, trying to
dereferencing danglig pointer
// If try block is disabled, everything goes fine.

// I experienced this problem in my production code which used
boost::intrusive_ptr class.
// I wrote similar class (CountingPtr) for simplicty's sake (and to
kill dependencies) and results are the same - program crashes

// tested on compilers: MS VS.NET 2003 (both original & SP1)

#include <iostream>
#include <cassert>

using namespace std;

struct IRefCounted
{
virtual void addRef() = 0;
virtual void release() = 0;

virtual ~IRefCounted() {};
};

struct ILogger : public IRefCounted
{
void virtual write(const char * text) = 0;
};

class Logger : public ILogger
{
int m_ref;
~Logger(){}
public:
Logger() : m_ref(0)
{
}

void addRef()
{
m_ref++;
}

void release()
{
if(--m_ref == 0)
delete this;
}

void write(const char * text)
{
cout << text << endl;
}
};

template<typename T>
class CountingPtr
{
T * m_t;

public:
CountingPtr(T * t, bool addRef = true) : m_t(t)
{
assert(t!=0);
if(addRef)
t->addRef();
}

~CountingPtr()
{
if(m_t)
m_t->release();
}

CountingPtr&operator=(const CountingPtr & rhs)
{
if(this == &rhs)
assert(false);
else
{
m_t = rhs.m_t;
m_t->addRef();

}
return *this;
}

T * operator->()
{
return m_t;
}

CountingPtr(const CountingPtr & rhs)
{
*this = rhs;
}
};

typedef CountingPtr<ILoggerCLoggerPtr;
void use(CLoggerPtr logger)
{
logger->write("use");
}

class Loggable
{
public:
Loggable(CLoggerPtr logger) : m_logger(logger)
{}

private:
CLoggerPtr m_logger;
};

class X : public Loggable
{
public:
X(CLoggerPtr logger)
try : Loggable(logger) // comment try block out to
get working code!
{}
catch(std::runtime_error & )
{
throw;
};
};

int main(int argc, char* argv[])
{
try
{
CLoggerPtr logger(new Logger());
use(logger);

{
X y1(logger); // THIS line decrements ref counter by 2 in case try
block is active
}

{
X y2(logger); // OOPS IS HERE! If try block is in act, program tries
to reference dangling pointer
}

return 0;
}
catch(exception & ex)
{
cout << "Exception: " << ex.what() << endl;
return EXIT_FAILURE;
}
catch(...)
{
cout << "(...) exception" << endl;
return EXIT_FAILURE;
}
}

Sep 26 '06 #1
Share this Question
Share on Google+
4 Replies


P: n/a
ks***********@yandex.ru wrote:
This message was originally posted to comp.lang.c++.moderated
----------------------------------------------------------------------------------------------

Hi!

I face a problem in my production code. I could deduce this problem to
program shown below. It seems, that try-block in constructor doesnt
work as it should (compared to case where no try block exists at all).
I tested this small program on my MSVC .NET Pro 2003 (and separately on
PC with MSVC2003 SP1 installed). In both cases I experienced the same
behaviour - access violation. Please see comment inside the program
body. To get this sample work - just comment out try block in ctor.

Have anyone faced such behaviour before? Is there known workarounds?
Thanks.
----
// ref_count.cpp : ctor try block invalid behaviour test

// if ctor uses try block (X::X), program crashes, trying to
dereferencing danglig pointer
// If try block is disabled, everything goes fine.

// I experienced this problem in my production code which used
boost::intrusive_ptr class.
// I wrote similar class (CountingPtr) for simplicty's sake (and to
kill dependencies) and results are the same - program crashes

// tested on compilers: MS VS.NET 2003 (both original & SP1)

#include <iostream>
#include <cassert>

using namespace std;

struct IRefCounted
{
virtual void addRef() = 0;
virtual void release() = 0;

virtual ~IRefCounted() {};
};

struct ILogger : public IRefCounted
{
void virtual write(const char * text) = 0;
};

class Logger : public ILogger
{
int m_ref;
~Logger(){}
public:
Logger() : m_ref(0)
{
}

void addRef()
{
m_ref++;
}

void release()
{
if(--m_ref == 0)
delete this;
}

void write(const char * text)
{
cout << text << endl;
}
};

template<typename T>
class CountingPtr
{
T * m_t;

public:
CountingPtr(T * t, bool addRef = true) : m_t(t)
{
assert(t!=0);
if(addRef)
t->addRef();
}

~CountingPtr()
{
if(m_t)
m_t->release();
}

CountingPtr&operator=(const CountingPtr & rhs)
{
if(this == &rhs)
assert(false);
else
{
m_t = rhs.m_t;
m_t->addRef();

}
return *this;
}

T * operator->()
{
return m_t;
}

CountingPtr(const CountingPtr & rhs)
{
*this = rhs;
}
};

typedef CountingPtr<ILoggerCLoggerPtr;
void use(CLoggerPtr logger)
{
logger->write("use");
}

class Loggable
{
public:
Loggable(CLoggerPtr logger) : m_logger(logger)
{}

private:
CLoggerPtr m_logger;
};

class X : public Loggable
{
public:
X(CLoggerPtr logger)
try : Loggable(logger) // comment try block out to
get working code!
{}
catch(std::runtime_error & )
{
throw;
};
};

int main(int argc, char* argv[])
{
try
{
CLoggerPtr logger(new Logger());
use(logger);

{
X y1(logger); // THIS line decrements ref counter by 2 in case try
block is active
}

{
X y2(logger); // OOPS IS HERE! If try block is in act, program tries
to reference dangling pointer
}

return 0;
}
catch(exception & ex)
{
cout << "Exception: " << ex.what() << endl;
return EXIT_FAILURE;
}
catch(...)
{
cout << "(...) exception" << endl;
return EXIT_FAILURE;
}
}
This code (with the try block) works fine with g++. It even passes a
valgrind check. Maybe, you are better of in a compiler specific news group.
Also, you might consider submitting a bug report to your compiler vendor.
Best

Kai-Uwe Bux
Sep 26 '06 #2

P: n/a
Thanks,

Could someone recommend me alive group related to MS VC++ compiler?

Thanks,
Kirill

Sep 27 '06 #3

P: n/a
ks***********@yandex.ru wrote:
Thanks,

Could someone recommend me alive group related to MS VC++ compiler?

Thanks,
Kirill
http://www.parashift.com/c++-faq-lit...t.html#faq-5.9
Sep 27 '06 #4

P: n/a
Hi!

This discusion is mode here -
http://groups.google.com/group/comp....b4bc995e3975e6

Regards,
Kirill

Sep 27 '06 #5

This discussion thread is closed

Replies have been disabled for this discussion.