Is it wrong to use auto_ptr with new char[n]

2019-04-19 01:34发布

问题:

If I declare a temporary auto deleted character buffer using

std::auto_ptr<char> buffer(new char[n]);

then the buffer is automatically deleted when the buffer goes out of scope. I would assume that the buffer is deleted using delete.

However the buffer was created using new[], and so strictly speaking the buffer should be deleted using delete[].

What possibility is there that this mismatch might cause a memory leak?

回答1:

The behaviour of calling delete on a pointer allocated with new[] is undefined. As you assumed, auto_ptr does call delete when the smart pointer goes out of scope. It's not just memory leaks you have to worry about -- crashes and other odd behaviours are possible.

If you don't need to transfer the ownership of the pointer, Boost's scoped_array class might be what you're looking for.



回答2:

I would use a vector of char as the buffer.

std::vector<char>    buffer(size);

read(input,&buffer[0],size);

Basically you don't even want to call new if you don't need to.
A vector provides a run-time sized buffer that you can use just like an array (buffer).

The best part is that the vector cleans up after itself and the standard guarantees that all element in the vector will be in contigious storage. Perfect for a buffer.

Or more formaly the guarantee is:

(&buffer[0]) + size == (&buffer[size])


回答3:

That yields undefined behaviour (could be worse than memory leak, for instance heap corruption) try boost's scoped_array or shared_array instead.



回答4:

Calling delete on data allocated with new[] is undefined. This means that the compiler may generate code that may do anything. However in this case it probably works since there's no need to destruct the individual chars in the array, just the array itself.

Still since this behavior is undefined, I would strongly recommend using std::vector<char> or boost::scoped_array<char> / boost::shared_array<char> instead. All are perfectly viable and superior options to using std::auto_ptr<> in this case. If you use std::vector you also have the possibility of dynamically grow the buffer if required.



回答5:

Is there a good reason not to use std::string? std::vector, as other have suggested? What you're doing is wrong, but without knowing what you're trying to do recommending something else is difficult.



回答6:

Yes, it is wrong. Wrap with a trivial wrapper.

typedef< typename T_ >
struct auto_vec{
  T_* t_;
  auto_vec( T_* t ): t_( t ) {}
  ~auto_vec() { delete[] t_; }
  T_* get() const { return t_; }
  T_* operator->() const { return get(); }
  T_& operator*() const { return *get(); }
  /* you should also define operator=, reset and release, if you plan to use them */
}

auto_vec<char> buffer( new char[n] );


回答7:

A few years have passed since the question was asked.

But I hit this page from a search, so I figured I might as well note: std::unique_ptr, the C++11 replacement for auto_ptr, can handle deletion of objects created with new[].

There are two versions of std::unique_ptr: 1) Manages the lifetime of a single object (e.g. allocated with new) 2) Manages the lifetime of a dynamically-allocated array of objects (e.g. allocated with new[])

cppreference unique_ptr



回答8:

This seems awful complex for a very simple solution. What's wrong with you using

 char *c=new char[n] 

here, and then deleting it? Or, if you need a bit more dynamic solution,

vector<char> c

Occam's Razor, man. :-)