2

I read C++: auto_ptr + forward declaration? and its answers, especially the accepted one and I'm aware of the pitfalls when combining auto_ptr and forward declarated classes. But I'm encountering runtime problems with this same pattern that seems not to be covered by this Q&A (and all other auto_ptr-tagged Questions I checked).

When destroying my Outer-like class[1], I sometimes get an access violation, sometimes I only observe missing destructor calls.

// Outer.h - an example header
#include <uncopyable.h>
#include <memory>
class Inner;

class Outer: private Uncopyable
{
public:
    Outer()
    ~Outer();
private:
    std::auto_ptr<Inner> inner;
};

I'm implementing constructor and destructor in the cpp file and there the definition of the Inner type is present.

// Outer.cpp - an example implementation
#include "Outer.h" //< I use this include order to ensure compileability
#include "Inner.h" //< for units including Outer.h without preconditions

Outer::Outer(): inner(new Inner) {}

Outer::~Outer() {}

The described problems disappear if I:

  • include Inner.h within Outer.h or
  • explicitly calling inner.reset()

I work on legacy code that compiles only with C++-Builder 6, so I've to stick to std::auto_ptr since it's the only smart_ptr implementation the compiler seems to support, so there is (currently) no alternative to this type (that I know is deprecated by C++11).

My question: What am I doing wrong here, or is it maybe a well-known bug in BCB6[2]?


Additional Remark I expected that using auto_ptr on uncomplete types would be safe having read Herb Sutter's article Using auto_ptr Effectively, the section Wrapping Pointer Data Members deals with it. The problems I describe above are therefore a very confusing experience.


  • [1] This example is cut down to discuss the formal structure of auto_ptr usage.
  • [2] Borland C++ 5.6.4, and the STL shipped with C++-Builder 6 (upd4)
Community
  • 1
  • 1
Wolf
  • 9,679
  • 7
  • 62
  • 108
  • 2
    have you tried if you have access to std::tr1::shared_ptr? – tillaert Jun 19 '14 at 14:59
  • Is `Outer` intended to be a type that can be copied? **If yes**, what should `inner` do then?. **If no**, why is `inner` not a raw pointer that is handled in the destructor? – Drew Dormann Jun 19 '14 at 15:02
  • @tillaert not so far. (the use of auto_ptr is also encouraged by the BCB6 developer's guide, which means it works well with the VCL) – Wolf Jun 19 '14 at 15:02
  • @DrewDormann no it inherits an `Uncopyable` class for this purpose. – Wolf Jun 19 '14 at 15:03
  • @DrewDormann inner is not a raw pointer, because it's a really "fat class" – Wolf Jun 19 '14 at 15:04
  • @Wolf I understand, partially. Maybe there's a misunderstanding regarding "fat classes" or pointers. An `auto_ptr` behaves like a raw pointer, only with _special copying and deleting rules_. And as you say, there is no copying happening here. Put another way, the "fatness" of a class should never affect the decision between using a raw pointer and an `auto_ptr`. – Drew Dormann Jun 19 '14 at 15:06
  • @DrewDormann yes maybe it's a bad idea to use auto_ptr for memory management in classes. But also a whole lot of delete statements can be confusing, sometimes you'll miss one. My goal was to get the deletion automated. – Wolf Jun 19 '14 at 15:12
  • I see now. You never thought that `auto_ptr` was needed, but you'd like the bookkeeping of a smart pointer and you seem only to have access to the smart pointer that has caused so _many problems like the one you're having_. I'd suggest answering the comment I've just upvoted above and if you're still stuck, making do with ugly, fat `delete`. Good luck! – Drew Dormann Jun 19 '14 at 15:18
  • @Wolf: show the inheritance from `Uncopyable` in your question, otherwise it looks like a rule-of-3 violation. – Ben Voigt Jun 19 '14 at 15:34

1 Answers1

2

It's going to be easier to fix the code to compile on a newer compiler with unique_ptr support than to fix auto_ptr (Why do you think the Standard committee killed it completely? Because they considered it unfixable).

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • +1 yes, seems so. Also the comments led me to this conclusion. Bootstrapping Boost is heavy but worth the work. There's so much to do when migrating and fixing at the same time... – Wolf Jun 19 '14 at 15:36