auto_ptr<istream> problem

Discussion in 'C++' started by james.lawton@gmail.com, Jun 23, 2008.

  1. Guest

    Hi,

    I'm having a problem that I can't diagnose. I'm creating istreams of
    unknown types, and want to manage them on the stack, co I'm passing
    around ownership-holding pointers. Usually, I would use
    std::auto_ptr<std::istream>, but it seems to be deallocating early, as
    the call to read(...) below breaks.

    I've condensed a test case. Using my own pointer works fine, but using
    auto_ptr does not (see USE_AUTO_PTR). I solved the issue by a little
    trial and error, but I don't understand the cause.

    Help would be greatly appreciated. I apologise if I'm simply being
    idiotic, but I've been trying to work this out for days.

    I'm compiling under Visual Studio 2005 (cl.exe version 14.00.50727.42)

    -- James


    // ---------- Begin ptr_test.cpp ----------

    #include <algorithm>
    #include <istream>
    #include <fstream>
    #include <memory>
    using namespace std;

    // Ownership transfering pointer to input
    stream //////////////////////

    //#define USE_AUTO_PTR

    #if defined(USE_AUTO_PTR)
    typedef auto_ptr<istream> istream_ptr;
    #else

    /* Not using copy constructor in example, so I won't bother writing
    * a standards compliant one here. Nor assignment operator. Instead
    * I'll make them private to be sure they're not generated.
    */
    template <class T>
    struct ptr {
    ptr( T * ptr ) : _ptr( ptr ) {}
    //ptr( ptr<T> & other ) : _ptr( 0 ) { swap( other ); }
    ~ptr() { if ( _ptr ) delete _ptr; }
    T * operator->() const { return _ptr; }
    private:
    ptr( ptr<T> const & );
    ptr<T> & operator=( ptr<T> const & );
    //void swap( ptr<T> & other ) { std::swap( _ptr, other._ptr ); }
    T * _ptr;
    };
    typedef ptr<istream> istream_ptr;

    #endif

    // Simple test
    case ///////////////////////////////////////////////////

    int main() {
    istream_ptr in = new fstream( "ptr_test.cpp", ios::binary );
    char ch;
    in->read( &ch, 1 );
    return 0;
    }

    // ---------- End ptr_test.cpp ----------
    , Jun 23, 2008
    #1
    1. Advertising

  2. Rolf Magnus Guest

    wrote:

    > Hi,
    >
    > I'm having a problem that I can't diagnose. I'm creating istreams of
    > unknown types, and want to manage them on the stack, co I'm passing
    > around ownership-holding pointers. Usually, I would use
    > std::auto_ptr<std::istream>, but it seems to be deallocating early, as
    > the call to read(...) below breaks.
    >
    > I've condensed a test case. Using my own pointer works fine, but using
    > auto_ptr does not (see USE_AUTO_PTR). I solved the issue by a little
    > trial and error, but I don't understand the cause.


    Your program below doesn't compile here on my compiler (and I wouldn't
    expect it to), neither with the #define, nor without.

    > Help would be greatly appreciated. I apologise if I'm simply being
    > idiotic, but I've been trying to work this out for days.
    >
    > I'm compiling under Visual Studio 2005 (cl.exe version 14.00.50727.42)
    >
    > -- James
    >
    >
    > // ---------- Begin ptr_test.cpp ----------
    >
    > #include <algorithm>
    > #include <istream>
    > #include <fstream>
    > #include <memory>
    > using namespace std;
    >
    > // Ownership transfering pointer to input
    > stream //////////////////////
    >
    > //#define USE_AUTO_PTR
    >
    > #if defined(USE_AUTO_PTR)
    > typedef auto_ptr<istream> istream_ptr;
    > #else
    >
    > /* Not using copy constructor in example, so I won't bother writing
    > * a standards compliant one here. Nor assignment operator. Instead
    > * I'll make them private to be sure they're not generated.
    > */
    > template <class T>
    > struct ptr {
    > ptr( T * ptr ) : _ptr( ptr ) {}
    > //ptr( ptr<T> & other ) : _ptr( 0 ) { swap( other ); }
    > ~ptr() { if ( _ptr ) delete _ptr; }
    > T * operator->() const { return _ptr; }
    > private:
    > ptr( ptr<T> const & );
    > ptr<T> & operator=( ptr<T> const & );
    > //void swap( ptr<T> & other ) { std::swap( _ptr, other._ptr ); }
    > T * _ptr;
    > };
    > typedef ptr<istream> istream_ptr;
    >
    > #endif
    >
    > // Simple test
    > case ///////////////////////////////////////////////////
    >
    > int main() {
    > istream_ptr in = new fstream( "ptr_test.cpp", ios::binary );


    Try:

    istream_ptr in(new fstream( "ptr_test.cpp", ios::binary ));

    That avoids creating a temporary, for which a copy constructor would be
    needed that takes a const istream_ptr as argument. std::auto_ptr doesn't
    have that (and neither does your class, so it shouldn't compile either).

    > char ch;
    > in->read( &ch, 1 );
    > return 0;
    > }
    >
    > // ---------- End ptr_test.cpp ----------
    Rolf Magnus, Jun 23, 2008
    #2
    1. Advertising

  3. >         istream_ptr in = new fstream( "ptr_test.cpp", ios::binary );

    Visual Studio 2005 has a buggy implementation of std::auto_ptr where
    this code compiles, but has the side effect that either the memory is
    deleted twice or that the memory is deleted directly after that
    statement, I don't remember.

    Write this instead:

    istream_ptr in(new fstream( "ptr_test.cpp", ios::binary ));

    Regards,
    Anders Dalvander
    Anders Dalvander, Jun 23, 2008
    #3
  4. Guest

    On 23 Jun, 03:51, Rolf Magnus <> wrote:
    > Your program below doesn't compile here on my compiler (and I wouldn't
    > expect it to), neither with the #define, nor without.


    Thank you for pointing it out. In fact, I hadn't explicitly turned off
    the "language extensions" in Visual Studio, and it was optimising away
    the copy constructor without so much as a warning for my pointer
    class.

    For auto_ptr, it implicitly converted to auto_ptr_ref, then
    constructed from that, which is fair enough. In fact, my actual
    pointer class does have an implicit conversion and pseudo-copy-
    constructor similar to auto_ptr, so that wasn't my problem.

    I found my problem in the full program, and I show it below in the
    function loadResource. Rather than (as I hoped) using
    auto_ptr<istream>::auto_ptr( istream * ), the return statement is in
    fact calling auto_ptr_ref<istream>::auto_ptr_ref( void * ) then
    auto_ptr( auto_ptr_ref<istream> & ). The pointer stored in the
    auto_ptr_ref is statically cast to (auto_ptr<istream> *) when it is
    really a (ifstream *) at heart. Cue problems.

    istream_ptr loadResource( string const & name ) {
    return new fstream( name.c_str(), ios::binary );
    // Above line should be the following
    //return istream_ptr( new fstream( name.c_str(), ios::binary ) );
    }

    int main() {
    istream_ptr in = loadResource( "ptr_test.cpp" );
    char ch;
    in->read( &ch, 1 );
    return 0;
    }


    > > // ---------- Begin ptr_test.cpp ----------

    >
    > > #include <algorithm>
    > > #include <istream>
    > > #include <fstream>
    > > #include <memory>
    > > using namespace std;

    >
    > > // Ownership transfering pointer to input
    > > stream //////////////////////

    >
    > > //#define USE_AUTO_PTR

    >
    > > #if defined(USE_AUTO_PTR)
    > > typedef auto_ptr<istream> istream_ptr;
    > > #else

    >
    > > /* Not using copy constructor in example, so I won't bother writing
    > >  * a standards compliant one here. Nor assignment operator. Instead
    > >  * I'll make them private to be sure they're not generated.
    > >  */
    > > template <class T>
    > > struct ptr {
    > > ptr( T * ptr ) : _ptr( ptr ) {}
    > > //ptr( ptr<T> & other ) : _ptr( 0 ) { swap( other ); }
    > > ~ptr() { if ( _ptr ) delete _ptr; }
    > > T * operator->() const { return _ptr; }
    > > private:
    > > ptr( ptr<T> const & );
    > > ptr<T> & operator=( ptr<T> const & );
    > > //void swap( ptr<T> & other ) { std::swap( _ptr, other._ptr ); }
    > > T * _ptr;
    > > };
    > > typedef ptr<istream> istream_ptr;

    >
    > > #endif

    >
    > > // Simple test
    > > case ///////////////////////////////////////////////////

    >
    > > int main() {
    > > istream_ptr in = new fstream( "ptr_test.cpp", ios::binary );

    >
    > Try:
    >
    > istream_ptr in(new fstream( "ptr_test.cpp", ios::binary ));
    >
    > That avoids creating a temporary, for which a copy constructor would be
    > needed that takes a const istream_ptr as argument. std::auto_ptr doesn't
    > have that (and neither does your class, so it shouldn't compile either).
    >
    > > char ch;
    > > in->read( &ch, 1 );
    > > return 0;
    > > }

    >
    > > // ---------- End ptr_test.cpp ----------
    , Jun 23, 2008
    #4
  5. Guest

    On 23 Jun, 13:32, Anders Dalvander <> wrote:
    > >         istream_ptr in = new fstream( "ptr_test.cpp", ios::binary );

    >
    > Visual Studio 2005 has a buggy implementation of std::auto_ptr where
    > this code compiles, but has the side effect that either the memory is
    > deleted twice or that the memory is deleted directly after that
    > statement, I don't remember.
    >
    > Write this instead:
    >
    > istream_ptr in(new fstream( "ptr_test.cpp", ios::binary ));
    >
    > Regards,
    > Anders Dalvander


    Thank you, Anders. I managed to discover this (eventually) and just
    posted my description of it before I saw this post. I think this
    should be a warning to anyone who wants an object to construct either
    from a pointer (especially in a template) or an object with an
    implicit conversion from (void *)
    , Jun 23, 2008
    #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. Siemel Naran

    auto_ptr<Derived> to auto_ptr<Base>

    Siemel Naran, Jan 10, 2005, in forum: C++
    Replies:
    2
    Views:
    1,534
    Dave Rahardja
    Jan 11, 2005
  2. Aaron Gray

    "istream" problem

    Aaron Gray, May 4, 2007, in forum: C++
    Replies:
    0
    Views:
    294
    Aaron Gray
    May 4, 2007
  3. Colonel
    Replies:
    2
    Views:
    561
    Jim Langston
    Sep 29, 2007
  4. Sousuke
    Replies:
    9
    Views:
    1,128
    Bart van Ingen Schenau
    Mar 16, 2010
  5. xmllmx
    Replies:
    5
    Views:
    573
    Jorgen Grahn
    Jun 15, 2010
Loading...

Share This Page