Microsoft KB Archive/129617

= FIX: Destructor Called on Non Constructed Temporary =

Article ID: 129617

Article Last Modified on 7/5/2005

-

APPLIES TO


 * Microsoft Visual C++ 1.5 Professional Edition
 * Microsoft Visual C++ 1.51
 * Microsoft Visual C++ 1.52 Professional Edition
 * Microsoft Visual C++ 2.0 Professional Edition
 * Microsoft Visual C++ 2.1

-



This article was previously published under Q129617



SYMPTOMS
The destructor of a class is called on a temporary that was never constructed if all the following conditions exist:


 * Two classes A and B are created.
 * A global function takes an argument of class B by value.
 * A conversion operator is used to convert from class A to class B.
 * The global function is called with an item of class A.

The destructor being called for an object that was never constructed can cause a general protection (GP) fault or other memory errors at run time.



WORKAROUND
Listed below in order of preference are three workarounds to this problem:


 * Define a conversion constructor in class B instead of a conversion operator in class A. -or-


 * Define the function to take an argument of "const B &" instead of taking class B by value. -or-


 * Explicitly instantiate a B object and call the global function with the instance of the B object.

The first workaround produces much cleaner code than the other two workarounds. See the sample code listed below for further details.



STATUS
Microsoft has confirmed this to be a bug in the Microsoft products listed at the beginning of this article. This problem was fixed in Microsoft Visual C++, 32-bit Edition, version 4.0.



MORE INFORMATION
The sample code below can be used to reproduce this problem. If the program is complied with no options, the following output is displayed when the program is run:

-- A ctor called

-- Class A -> Class B conversion called

-- B ctor called, Created B: 1245064

-- B copy ctor, Created B: 1245096

-- B dtor called, Destroyed B: 1245064

-- Calling function test(B) on B: 1245076

-- B dtor called, Destroyed B: 1245076

This B was never constructed!

-- B dtor called, Destroyed B: 1245096

-- A dtor called

Sample Code to Reproduce Problem
/* Compile options needed, choose one of the following: none          - To demonstrate the problem. /DWORKAROUND1 - For workaround 1. /DWORKAROUND2 - For workaround 2. /DWORKAROUND3 - For workaround 3.


 * 1) include 

class A;

class B { B *pBthis; public: B { pBthis = this; cout << "-- B ctor called, Created B: " << (long)this << endl; }  B(const A&) { pBthis = this; cout << "-- B(A) ctor called, Created B: " << (long)this << endl; }  B( const B& b ) { pBthis = this; cout << "-- B copy ctor, Created B: " << (long)this << endl; }  ~B { cout << "-- B dtor called, Destroyed B: " << (long)this << endl; if (pBthis != this) cout << "   This B was never constructed!" << endl; } };
 * 1) ifdef WORKAROUND1
 * 1) endif

class A { public:

A { cout << "-- A ctor called" << endl; } ~A { cout << "-- A dtor called" << endl; }

operator B { cout << "-- Class A -> Class B conversion called" << endl; B b1; return b1; }
 * 1) ifndef WORKAROUND1
 * 1) endif

};

void test(const B &b) void test(B b) { cout << "-- Calling function test(B) on B: " << (long)(&b) << endl; }
 * 1) ifdef WORKAROUND2
 * 1) else
 * 1) endif

int main {  A a;
 * 1) ifdef WORKAROUND3

B b(a); test(b); test(a); return 0; }
 * 1) else
 * 1) endif

Additional query words: 1.00 1.50 1.51 1.52 2.00 2.10 8.0 8.00 8.0c 8.00c 9.0 9.00 GPF

Keywords: kbbug kbfix KB129617

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.