what's wrong with std::auto_ptr<int> ptr(new int[100]);?
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 14 of 14

Thread: what's wrong with std::auto_ptr<int> ptr(new int[100]);?

  1. #1
    Join Date
    Sep 2006
    Posts
    141

    Question what's wrong with std::auto_ptr<int> ptr(new int[100]);?

    what's wrong with std::auto_ptr<int> ptr(new int[100]) ?

    Seems it works....?

  2. #2
    Join Date
    Aug 2000
    Location
    West Virginia
    Posts
    7,712

    Re: what's wrong with std::auto_ptr<int> ptr(new int[100]);?

    What do you think it does ? (and what do you want it to do ?).

    1) if you want it to create a pointer to an int and initialize that
    int to 100 , use () instead of []

    Code:
    std::auto_ptr<int> ptr(new int(100));
    2) what I assume that your code does ... allocates memory to
    hold 100 ints ... the problem ... when the auto_prt does its
    "delete" ... it does not do a "delete []" ... just "delete"

  3. #3
    Join Date
    Feb 2005
    Location
    "The Capital"
    Posts
    5,306

    Re: what's wrong with std::auto_ptr<int> ptr(new int[100]);?

    Take a read about smart pointers and deleters - Custom deleters with smart pointers

    For your case, the right fit is something like scoped_array<> - Boost - smart pointers. Or, you can write your own version of auto_ptr and name is appropriately, for example, auto_ptr_array<> and have the same code that auto_ptr has except that instead of delete calls, put in a delete[] call. You can also implement auto_ptr_array<> in terms of auto_ptr in order to avoid the code duplicacy, though having a uniform interface eases understanding of it.

    The way you show above causes undefined behaviour.
    Last edited by exterminator; July 10th, 2007 at 04:57 AM.

  4. #4
    Join Date
    Oct 2000
    Location
    London, England
    Posts
    4,773

    Re: what's wrong with std::auto_ptr<int> ptr(new int[100]);?

    auto_ptr cannot be used on arrays because it calls the wrong sort of delete. You shouldn't actually need to use it, because you should be using vector.

    If you really want auto_ptr's ownership-transfer (which scoped_array doesn't have) because you want to return a large array from a function which would be expensive to copy and you wish to do it many times (although passing in the vector to fill is preferable) then you might consider using boost::shared_array.

    I do actually have a movable scoped pointer in my codebase which also allows a custom deleter (thus allowing arrays which use delete[]). In the new C++ standard, move semantics will be part of the syntax using operator && however for now you have to simulate it yourself. I do this by an explicit "mover" which you have to attach back to the object or it leaves a leak. Whilst you could simply return the raw pointer, it is more obvious when you return the mover that it must be attached (and you cannot access it as the smart-pointer holder has friendship and has the only access to it).

    The simple implementation here is:
    Code:
    template < typename T >
    class MovableScopedArray
    {
    public:
       class Mover
       {
           friend class MovableScopedArray<T>;
           T* data;
           size_t size;
           bool owns;
    
          MovableScopedArray() : data( 0 ), size( 0 ), owns( true ) {}
    
          MovableScopedArray( const T * d, size_t z )
              : data( d ), size( z ), owns( true )     
         {
          }
       } m;
    
       MovableScopedArray() {}
       MovableScopedArray( T* data, size_t size ) : m( data, size ) {}
       MovableScopedArray( Mover mov ) : m( mov ) {}
    
       void swap( MovableScopedArray & other )
       {
             std::swap( m.data, other.m.data );
             std::swap( m.size, other.m.size );
             std::swap( m.owns, other.m.owns );
       }
    
       ~MovableScopedArray()
       {
           if ( m.owns ) { delete [] m.data; }
       }
    
       Mover move()
      {
           Mover mcopy( m );
            m.owns = false;
           return mcopy;
       }
    
       const T & operator[]( size_t idx ) const
       {
          return m.data[ idx ];
       }
    
       T& operator[]( size_t idx )
      {
           return m.data[ idx ];
       }
       
      size_t size() const
      {
           m.size;
      }
    
       private:
      // make it non-copyable
         MovableScopedArray( const MovableScopedArray & );
        MovableScopedArray & operator=( cosnt MovableScopedArray & );
     
    };
    Note that I haven't test this, and it is not safe across library boundaries because the smart-pointer calls delete[] not through a v-table. (My version has a pointer to deleter_base which calls a virtual method dispose(), boost does something similar, and when you pass in a deleter of any type it is able to create a derivation of the deleter base that holds an instance to the deleter!).
    Last edited by NMTop40; July 12th, 2007 at 10:09 AM.

  5. #5
    Join Date
    Sep 2006
    Posts
    141

    Re: what's wrong with std::auto_ptr<int> ptr(new int[100]);?

    Quote Originally Posted by Philip Nicoletti
    2) what I assume that your code does ... allocates memory to
    hold 100 ints ... the problem ... when the auto_prt does its
    "delete" ... it does not do a "delete []" ... just "delete"
    Why didn't people implement auto_ptr with a "delete[]"??? Since delete[] can be used for single pointer as well, for example:
    Code:
    	char * tmpi = new char;
    	delete[] tmpi;
    delete[] works well here.

  6. #6
    Join Date
    Sep 2006
    Posts
    141

    Re: what's wrong with std::auto_ptr<int> ptr(new int[100]);?

    Quote Originally Posted by Philip Nicoletti
    2) what I assume that your code does ... allocates memory to
    hold 100 ints ... the problem ... when the auto_prt does its
    "delete" ... it does not do a "delete []" ... just "delete"
    Why didn't people implement auto_ptr with a "delete[]" in std::auto_ptr in the first place??? Since delete[] can be used for single pointer as well, for example:
    Code:
    	char * tmpi = new char;
    	delete[] tmpi;
    delete[] works well here, doesn't it?

  7. #7
    Join Date
    Aug 2000
    Location
    West Virginia
    Posts
    7,712

    Re: what's wrong with std::auto_ptr<int> ptr(new int[100]);?

    Undefined results.

    1) for "arrays" , you can use vector

    2) I believe that an array version of auto_ptr is being added
    in the next version of the standard.

  8. #8
    Join Date
    Nov 2006
    Location
    Essen, Germany
    Posts
    1,344

    Re: what's wrong with std::auto_ptr<int> ptr(new int[100]);?

    As NMTop40 and Exterminator mentioned before:
    There are smart pointers with different deallocation policies in the boost library:
    - for objects there are shared_ptr and scoped_ptr (deleting by delete)
    - for arrays there are shared_array and scoped_array (deleting by delete[])

    When calling delete[] on a single object and delete on an array succeed then itīs compiler dependent and non-standard. These hacks will cause bad headache when migrating from one compiler to another, so better stick to the standard.
    Last edited by GNiewerth; July 10th, 2007 at 03:52 PM.

  9. #9
    Join Date
    Sep 2006
    Posts
    141

    Re: what's wrong with std::auto_ptr<int> ptr(new int[100]);?

    Does delete[] work for single pointer? For example:
    Code:
    	char * tmpi = new char;
    	delete[] tmpi;
    ?

  10. #10
    Join Date
    Aug 2000
    Location
    West Virginia
    Posts
    7,712

    Re: what's wrong with std::auto_ptr<int> ptr(new int[100]);?

    As I already mentioned ... undefined behavior

  11. #11
    Join Date
    Feb 2005
    Location
    "The Capital"
    Posts
    5,306

    Re: what's wrong with std::auto_ptr<int> ptr(new int[100]);?

    Quote Originally Posted by warrener
    Does delete[] work for single pointer? For example:
    Code:
    	char * tmpi = new char;
    	delete[] tmpi;
    Though you should stop experimenting/thinking about it at the moment you know its undefined behaviour but take a look at how the array form of delete might be implemented and why the interpretation of a single char allocation block differently can cause problems - http://www.parashift.com/c++-faq-lit...html#faq-16.14

    There can be many more implementations but lets just concentrate on those two.

    For the first where there is an extra allocation to remember the size you ask for at the runtime, if you used delete[] as above, the compiler might try to interpret the block before the pointer tmpi as being size but since that was not allocated in the first place - expect anything to happen, a crash or any other form of runtime error (depending upon how that error is translated on a particular system).

    For the second where array length association might not exist, it could cause anything depending upon a number of factors about the compiler implementation - it could leave the variable uninitialized - in which case the size could be anything - even 2 which goes beyond the buffer you allocated and again can cause any fault to the system/system free store. If the size is initialized to 0, it could leave the memory untouched and hence lost resulting in a leak.

    There can be many such interesting stories that you can write up. The key is, use auto_ptr what it is suited for, use delete/delete[] what it is suited for.

    There is a peculiarity to note though. If you do the allocation for the single element using array form of new - you could use delete[] for that single element. That is:
    Code:
    int * ptr = new int[1];
    delete[] ptr; //OK
    Well, not really a peculiarity, but yeah, something to note.

  12. #12
    Join Date
    Oct 2000
    Location
    London, England
    Posts
    4,773

    Re: what's wrong with std::auto_ptr<int> ptr(new int[100]);?

    There already is an "auto" for arrays, it's called vector.

  13. #13
    Join Date
    Feb 2005
    Location
    "The Capital"
    Posts
    5,306

    Re: what's wrong with std::auto_ptr<int> ptr(new int[100]);?

    Quote Originally Posted by NMTop40
    I do actually have a movable scoped pointer in my codebase which also allows a custom deleter (thus allowing arrays which use delete[]). In the new C++ standard, move semantics will be part of the syntax using operator && however for now you have to simulate it yourself. I do this by an explicit "mover" which you have to attach back to the object or it leaves a leak. Whilst you could simply return the raw pointer, it is more obvious when you return the mover that it must be attached (and you cannot access it as the smart-pointer holder has friendship and has the only access to it).
    How do you use it? For example, when returning from a function? Would you construct a MovableScopedArray object with the mover returned out of move()? In that case, MovableScopedArray would need a constructor that takes in the mover.

  14. #14
    Join Date
    Oct 2000
    Location
    London, England
    Posts
    4,773

    Re: what's wrong with std::auto_ptr<int> ptr(new int[100]);?

    Yes you are right, mine has one... I thought I'd implemented it there but will edit the post to insert it.

    ...

    OK- just did.

    Note that you still cannot assign to the Mover, you have to construct a new one or swap with an existing one. To swap you must create the new one and swap in one go thus:
    Code:
    MovableScopedArray<T>( func() ).swap( myScopedArray );
    where func() is a function that returns MovableScopedArray<T>::Mover.
    Last edited by NMTop40; July 12th, 2007 at 10:12 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This a Codeguru.com survey!


On-Demand Webinars (sponsored)