views:

1027

answers:

7

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?

+17  A: 

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.

Stephen Veiss
+7  A: 

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

nrl
+6  A: 

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.

Andreas Magnusson
+4  A: 

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])
Martin York
+4  A: 

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.

David Thornley
A: 

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. :-)

Paul Nathan
The point is to guarantee deletion. Using a smart pointer/array is safe against normal programming goofs as well as being smart enough to free the memory when exceptions occur. Directly using C arrays is asking for a memory leak.
Diastrophism
The whole point is we want to guarantee deleteion. Thus unwrapped RAW new is not a good answer. std::vector on the other hand is a good answer
Martin York
+1  A: 

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] );
Sanjaya R