Article: Q129617
Product(s): Microsoft C Compiler
Version(s): 1.0,1.5,1.51,1.52,2.0,2.1
Operating System(s):
Keyword(s): kbbuglist kbfixlist
Last Modified: 23-JUL-2001
-------------------------------------------------------------------------------
The information in this article applies to:
- Microsoft C/C++ Compiler (CL.EXE), included with:
- Microsoft Visual C++, versions 1.5, 1.51, 1.52
- *EDITOR Please do not choose this product*Microsoft Visual C++ 32-bit Edition* use 241, 265, 225, versions 1.0, 2.0, 2.1
-------------------------------------------------------------------------------
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.
*/
#include <iostream.h>
class A;
class B
{
B *pBthis;
public:
B() {
pBthis = this;
cout << "-- B ctor called, Created B: " << (long)this << endl;
}
#ifdef WORKAROUND1
B(const A&) {
pBthis = this;
cout << "-- B(A) ctor called, Created B: " << (long)this << endl;
}
#endif
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;
}
};
class A
{
public:
A() { cout << "-- A ctor called" << endl; }
~A() { cout << "-- A dtor called" << endl; }
#ifndef WORKAROUND1
operator B() {
cout << "-- Class A -> Class B conversion called" << endl;
B b1;
return b1;
}
#endif
};
#ifdef WORKAROUND2
void test(const B &b)
#else
void test(B b)
#endif
{
cout << "-- Calling function test(B) on B: " << (long)(&b) << endl;
}
int main()
{
A a;
#ifdef WORKAROUND3
B b(a);
test(b);
#else
test(a);
#endif
return 0;
}
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 : kbbuglist kbfixlist
Technology : kbVCsearch kbAudDeveloper kbCVCComp
Version : :1.0,1.5,1.51,1.52,2.0,2.1
Issue type : kbbug
Solution Type : kbfix
=============================================================================