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

8

14

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?

Triennial answered 4/11, 2008 at 9:31 Comment(0)
N
19

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.

Notch answered 4/11, 2008 at 9:40 Comment(0)
T
10

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])
Tollefson answered 4/11, 2008 at 18:12 Comment(0)
I
7

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

Insectarium answered 4/11, 2008 at 9:41 Comment(0)
M
6

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.

Miun answered 4/11, 2008 at 9:42 Comment(0)
F
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.

Forgiveness answered 4/11, 2008 at 18:20 Comment(0)
S
4

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] );
Swordcraft answered 10/11, 2008 at 20:20 Comment(0)
D
2

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

Decompress answered 17/7, 2012 at 0:33 Comment(2)
Wouldn't that be specific to "MSDN" (cl is the name of that compiler, though.)Fournier
Fair enough. Updated the reference to be general C++ rather than Microsoft-STL specific. The other answers were fine in 2008 when first asked but now that auto_ptr is long since deprecated, I just hope no newbie web surfer hits this page and thinks they need boost or their own wrapper or anything else when the good solution is in STL for free now.Decompress
T
0

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

Tamp answered 4/11, 2008 at 18:52 Comment(2)
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.Tack
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 answerTollefson

© 2022 - 2024 — McMap. All rights reserved.