This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug c++/12737] New: Class destructor never gets invoked even though its corresponding class constructor is invoked, and the object has gone out of scope. (Appears to be related to copy-constructor initialization with an argument that consists of an implicit user-defined cast operator that returns a CONST value.)


PLEASE REPLY TO gcc-bugzilla@gcc.gnu.org ONLY, *NOT* gcc-bugs@gcc.gnu.org.

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12737

           Summary: Class destructor never gets invoked even though its
                    corresponding class constructor is invoked, and the
                    object has gone out of scope.  (Appears to be related to
                    copy-constructor initialization with an argument that
                    consists of an implicit user-defined cast operator that
                    returns a CONST value.)
           Product: gcc
           Version: 3.2.3
            Status: UNCONFIRMED
          Severity: critical
          Priority: P1
         Component: c++
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: da0g+ at cs dot cmu dot edu
                CC: gcc-bugs at gcc dot gnu dot org
  GCC host triplet: Linux 2.4.20 #1-i686-001
GCC target triplet: i686-pc-linux-gnu

Under certain circumstances a class destructor is NEVER invoked, even
though its corresponding class constructor is invoked, and the object
has gone out of scope.

This creates problems with respect to smart pointers (and other
objects) that rely on matching constructor/destructor pairs.

This bug appears to stem from initializing the new object through
its copy constructor with a CONST value that is returned from an
implicitly invoked user-defined cast operator.

In the example code below:

FAILS:  operator const Foo & () { return foo; }
FAILS:  operator const Foo   () { return foo; }
WORKS:  operator       Foo & () { return foo; }
WORKS:  operator       Foo   () { return foo; }


Example code:

#define _CPP_BACKWARD_BACKWARD_WARNING_H
#include <iostream.h>

class Foo
{
public:
  char placeholder;
  Foo()  { cout << "foo constructor\n"; }
  ~Foo() { cout << "foo DESTRUCTOR\n"; }
  Foo(const Foo & theFoo) { cout << "foo COPY-constructor\n"; }
  Foo & operator=(const Foo & theFoo){cout << "foo operator=\n"; return *this;}
};


class Charlie
{
public:
  Foo foo;

  Charlie()  { cout << "charlie constructor\n"; }
  ~Charlie() { cout << "charlie DESTRUCTOR\n"; }
  Charlie(const Charlie & theCharlie) { cout << "charlie COPY-constructor\n"; }
  Charlie & operator=(const Charlie & theCharlie)
                                { cout << "charlie operator=\n"; return *this;}

  operator const Foo & () { return foo; }
};


static void bar ( Foo bar_foo )
{
  cout << "bar\n";
}

#define POUT(X) cout << # X << endl; X

int main()
{
  Foo foo;
  Charlie charlie;

  cout << endl << "Works fine:" << endl;
  POUT ( bar ( foo ) );

  cout << endl << "Works fine:" << endl;
  POUT ( const Foo & f = charlie );
  POUT ( bar ( f ) );

  cout << endl << "Works fine:" << endl;
  {
    POUT ( Foo f2 = charlie );
    POUT ( bar ( f2 ) );
  }

  cout << endl << "FAILS -- note the lack of DESTRUCTOR for bar_foo:" << endl;
  POUT ( bar ( charlie ) );

  cout << endl;
}



Example results:

% ./foo 
foo constructor
foo constructor
charlie constructor

Works fine:
bar ( foo )
foo COPY-constructor
bar
foo DESTRUCTOR

Works fine:
const Foo & f = charlie
bar ( f )
foo COPY-constructor
bar
foo DESTRUCTOR

Works fine:
Foo f2 = charlie
foo COPY-constructor
bar ( f2 )
foo COPY-constructor
bar
foo DESTRUCTOR
foo DESTRUCTOR

FAILS -- note the lack of DESTRUCTOR for bar_foo:
bar ( charlie )
foo COPY-constructor
bar

charlie DESTRUCTOR
foo DESTRUCTOR
foo DESTRUCTOR


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]