0

This is very similar to auto_ptr for arrays. However, my wrinkle is I don't want an initialized array, which is what a vector would provide (the const T& value = T()):

explicit vector(size_type count,
    const T& value = T(),
    const Allocator& alloc = Allocator());

I don't want the array initialized because its a large array and the values will be immediately discarded.

I'm currently hacking it with the following, but it feels like something is wrong with it:

//! deletes an array on the heap.
template <class T>
class AutoCleanup
{
public:
    AutoCleanup(T*& ptr) : m_ptr(ptr) { }
    ~AutoCleanup() { if (m_ptr) { delete[] m_ptr; m_ptr = NULL; }}

private:
    T*& m_ptr;
};

And:

// AutoCleanup due to Enterprise Analysis finding on the stack based array.
byte* plaintext = new byte[20480];
AutoCleanup<byte> cleanup(plaintext);

// Do something that could throw...

What does C++ provide for an array of a POD type that is uninitialized and properly deleted?


The project is C++03, and it has no external dependencies, like Boost.

Community
  • 1
  • 1
jww
  • 97,681
  • 90
  • 411
  • 885
  • you mean a non-Boost `boost::ptr_vector`? – Kos Sep 30 '15 at 14:23
  • 1
    Why would they be immediately discarded? What's the actual problem you are trying to solve? – Shoe Sep 30 '15 at 14:26
  • I don't think new[] and delete[] initializes the POD elements.. – David Haim Sep 30 '15 at 14:27
  • Note that `auto_ptr` has been deprecated since C++11 and will go away with C++17. – DevSolar Sep 30 '15 at 14:28
  • @ʎǝɹɟɟɟǝſ - *"Why would they be immediately discarded?"* - the values in the array are immediately over written. *"What's the actual problem you are trying to solve?"* - an Enterprise Analysis finding on a large array placed on the stack. I'm somewhat indifferent about it, but I want to ensure those who use analysis tools don't encounter a finding. – jww Sep 30 '15 at 14:34
  • @jww "large array placed on the stack" - you mean indirectly placed on the stack, i.e. heap-allocated, but lifetime is stack-bound? Or do you want it to be stack-allocated? – leemes Sep 30 '15 at 14:35
  • @Kos - Our only requirement is a [mostly] conforming C++ 03 Standard Library, like provided by GNU, LLVM, STLport or Dinkumware. We don't use Boost, so I'm not really familiar with its gadgets. – jww Sep 30 '15 at 14:37
  • I do not understand the question. Do you want an array of pointer-like objects or an array of pods? Do you want array or vector? – SergeyA Sep 30 '15 at 14:38
  • @leemes - the large array is stack based: `byte theArray[20480];`. I'm trying to move it to the heap: `byte* theArray = new byte[20480];` But I need to do so in an exception-safe way because the routine that uses it could throw an exception. – jww Sep 30 '15 at 14:41
  • @jww I'm not very clear on the nature of your problem. I'm not telling you to depend on Boost, just check if you're looking for an equivalent of something that's already there – Kos Sep 30 '15 at 14:49

1 Answers1

2

From your question, it's not easy to interpret what you actually need. But I guess you want an array which is stack-guarded (i.e. lifetime bound to the stack), heap-allocated, uninitialized, dynamically or statically sized, and compatible with pre-C++11 compilers.

auto_ptr can't handle arrays (because it doesn't call delete[] in its destructor, but rather delete).

Instead, I would use boost::scoped_array together with new[] (which doesn't initialize POD types afaik).

boost::scoped_array<MyPodType> a(new MyPodType[20480]);

If you don't want to use boost, you can reimplement scoped_array pretty easily by pasting the code together which this class includes from the boost library:

#include <cassert>
#include <cstddef>

// From <boost/checked_delete.hpp>:
template<class T>
inline void checked_array_delete(T * x)                                                                          
{
    typedef char type_must_be_complete[sizeof(T) ? 1 : -1];
    (void) sizeof(type_must_be_complete);
    delete [] x;
}

// From <boost/smartptr/scoped_array.hpp>:
template<class T>
class scoped_array
{
private:
    T * px;

    // Make this smart pointer non-copyable
    scoped_array(scoped_array const &);
    scoped_array & operator=(scoped_array const &);

    typedef scoped_array<T> this_type;

public:
    typedef T element_type;

    explicit scoped_array(T * p = 0) : px(p)  { }

    ~scoped_array() {
        checked_array_delete(px);
    }

    void reset(T * p = 0) {
        assert(p == 0 || p != px); // catch self-reset errors
        this_type(p).swap(*this);
    }

    T & operator[](std::ptrdiff_t i) const {
        assert(px != 0);
        assert(i >= 0);
        return px[i];
    }

    T * get() const {
        return px;
    }

    operator bool () const {
        return px != 0;
    }

    bool operator ! () const {
        return px == 0;
    }

    void swap(scoped_array & b) {
        T * tmp = b.px;
        b.px = px;
        px = tmp;
    }
};
leemes
  • 44,967
  • 21
  • 135
  • 183
  • Thanks leemes. I can't really tell if this is what I need. Will it ensure (1) the values created with `new []` are not initialized; and (2) the array is deleted with `delete []` upon destruction? If it satisfies those two criteria, then I'd be happy to accept. – jww Sep 30 '15 at 15:15
  • @Jarod42 Oh, you're right... I'll remove `explicit` then. – leemes Sep 30 '15 at 15:21
  • @jww AFAIK, both is true. This class simply wraps around `delete[]` and doesn't do any allocation or initialization. This is done when you create an instance of the wrapper class, since you give it just a pointer to the array to be deleted. There you use `new[]` which doesn't initialize POD types. – leemes Sep 30 '15 at 15:24
  • Perfect, thanks. All this time I thought I was doing something wrong (and too uninformed to figure out the C++ way). It looks like Boost and I approached the issue the same way. – jww Sep 30 '15 at 15:26
  • Yes... What you added in your question is pretty much the solution. The rest of my answer / the boost implementation is just convenience members for simple notation, for example `operator[]`. – leemes Sep 30 '15 at 16:05