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

Discussion in 'C++' started by ksukhonosenko@yandex.ru, Sep 26, 2006.

  1. Guest

    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<ILogger> CLoggerPtr;


    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, 2006
    #1
    1. Advertising

  2. Kai-Uwe Bux Guest

    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<ILogger> CLoggerPtr;
    >
    >
    > 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
    Kai-Uwe Bux, Sep 27, 2006
    #2
    1. Advertising

  3. Guest

    Thanks,

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

    Thanks,
    Kirill
    , Sep 27, 2006
    #3
  4. red floyd Guest

    red floyd, Sep 27, 2006
    #4
  5. Guest

    , Sep 27, 2006
    #5
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Apricot
    Replies:
    4
    Views:
    517
    velthuijsen
    Apr 16, 2004
  2. NVH
    Replies:
    8
    Views:
    478
    mlimber
    Jul 6, 2006
  3. Grizlyk
    Replies:
    8
    Views:
    472
    Grizlyk
    Nov 29, 2006
  4. , India

    copy ctor vs default ctor

    , India, Aug 15, 2007, in forum: C++
    Replies:
    2
    Views:
    402
    =?ISO-8859-1?Q?Erik_Wikstr=F6m?=
    Aug 15, 2007
  5. Anonymous
    Replies:
    2
    Views:
    371
    Victor Bazarov
    Aug 28, 2007
Loading...

Share This Page