Bug 38916 - auto_ptr_ref conversion incorrectly releases ownership
Summary: auto_ptr_ref conversion incorrectly releases ownership
Status: RESOLVED WONTFIX
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 4.3.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-01-19 21:24 UTC by Janis Johnson
Modified: 2010-02-05 12:57 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Janis Johnson 2009-01-19 21:24:22 UTC
The ISO C++ standard in section 20.4.5.3 defines the effects and postconditions of auto_ptr conversions.  It says that

  template<class Y> operator auto_ptr_ref<Y>() throw();

returns "an auto_ptr_ref<Y> that holds *this".  Unlike the other conversions in the same section, there is no call to release(), so after the call the original auto_ptr should still own the memory.

The following testcase is based on one from a testing group within IBM (not a customer-reported problem).  It shows that creating a reference to an auto_ptr releases the memory from that auto_ptr when it should not.  I see this behavior on powerpc*-linux for GCC 3.3 and later.  I haven't tried earlier versions.

------------------------------------------------------------------------
// Test the effects and postconditions of auto_ptr conversions, defined
// in the ISO C++ standard in section 20.4.5.3.

#include <memory>
extern "C" void abort (void);

int failures = 0;

#ifdef DBG
#include <iostream>
#define FAILURE(m)                                                      \
  {                                                                     \
    std::cout << "line " << __LINE__ << ":  " << m << std::endl;        \
    failures++;                                                         \
  }
#else
#define FAILURE(m) { failures++; }
#endif

struct X { };

int
main ()
{
  X* xptr = new X;

  std::auto_ptr<X> ap1 (xptr);
  if (ap1.get() != xptr)
    FAILURE ("ap1 does not own the memory")

  // Construct a reference to ap1; there should be no release.
  std::auto_ptr_ref<X> ref (ap1.operator std::auto_ptr_ref<X> ());
  if (ap1.get() != xptr)
    FAILURE ("ap1 no longer owns the memory after constructing a reference")

  // Construct ap2 from the reference.  ap2 should now own the memory
  // and ap1 should no longer hold it.
  std::auto_ptr<X> ap2(ref);
  if (ap2.get() != xptr)
    FAILURE ("ap2 does not own the memory after constructing from reference")
  if (ap1.get() != (X*)0)
    FAILURE ("ap1 is not zeroed after constructing ap2 from reference")

  if (failures != 0)
    abort ();

  return 0;
}
------------------------------------------------------------------------

elm3b145% /opt/gcc-nightly/trunk/bin/g++ -DDBG bug.cc
elm3b145% LD_LIBRARY_PATH=/opt/gcc-nightly/trunk/lib ./a.out
line 34:  ap1 no longer owns the memory after constructing a reference
Aborted
Comment 1 Paolo Carlini 2009-01-19 22:35:37 UTC
Note that auto_ptr is deprecated for the next Standard, replaced by unique_ptr (which we deliver in C++0x mode). In fact the specifications of auto_ptr are known to be irreparably broken.  That means we must be *extremely* careful here, if we touch the code we can destabilize an already brittle behavior.

Do we have evidence that other widespread implementations actually behave differently than libstdc++-v3 here?
Comment 2 Janis Johnson 2009-01-19 22:45:18 UTC
I assume that the person who sent me the test did so because it passes with some other implementation, but that doesn't mean it's widespread.  It's fine with me if you say it won't be fixed.
Comment 3 Paolo Carlini 2009-01-19 23:12:39 UTC
Please, double check that, if possible. Then we'll see...
By the way, we are essentially following Josuttis' implementation, in his book.
Comment 4 Janis Johnson 2009-01-26 18:42:46 UTC
Paolo, the person who reported the problem to me is no longer with IBM.  I've asked others in the same group to provide information about the origins of the test and what implementations are known to pass it, but it might take a long time to get that info.
Comment 5 Paolo Carlini 2009-01-26 19:08:45 UTC
Ok, take your time. For the reasons we already discussed we don't want to rush on this, in the meanwhile I will also try to collect more information.
Comment 6 Janis Johnson 2009-02-17 19:03:11 UTC
The original testcase is from outside IBM and is probably run by many library implementors.  That doesn't necessarily mean that many implementations pass this test.
Comment 7 Paolo Carlini 2010-02-05 12:57:06 UTC
At this point, I don't think we are going to do change the deprecated auto_ptr, so closing as WONTFIX.