DOCUMENT:Q132893 30-JUL-2001 [visualc] TITLE :PRB: Exceptions Thrown During Construction Can Orphan Memory PRODUCT :Microsoft C Compiler PROD/VER:2.0 2.1 4.0 4.2 5.0 OPER/SYS: KEYWORDS:kbcode kbCodeGen kbCompiler kbCPPonly kbVC ====================================================================== ------------------------------------------------------------------------------- The information in this article applies to: - The C/C++ Compiler (CL.EXE), included with: - Microsoft Visual C++, 32-bit Editions, versions 2.0, 2.1, 4.0 - Microsoft Visual C++, 32-bit Enterprise Edition, version 4.2 - Microsoft Visual C++, 32-bit Professional Edition, version 4.2 - Microsoft Visual C++, 32-bit Enterprise Edition, version 5.0 - Microsoft Visual C++, 32-bit Professional Edition, version 5.0 ------------------------------------------------------------------------------- SYMPTOMS ======== Memory that is dynamically allocated in a constructor can be orphaned when an exception is thrown in the constructor. CAUSE ===== When inside a constructor, the object is partially constructed, so the destructor is not called. While automatic data is freed during stack unwinding, memory that is dynamically allocated is not properly cleaned up. RESOLUTION ========== Two-phased construction of objects resolves this problem (see the following code sample). This way, the object is fully constructed, so when it is deleted, cleanup is handled correctly. Sample Code ----------- The following sample code shows both single- and two-phased construction for a class. /* Compile options needed: /MT /GX */ // Change the following line into a comment to show the problem: #define TWO_PHASED_CONSTRUCTION // Include the MFC debug memory allocation functions. You will see the // memory leaks reported by MFC when the application terminates when you // run the program in the Visual C++ debugger. #include "afx.h" #define new DEBUG_NEW class A { char *x; public: #ifndef TWO_PHASED_CONSTRUCTION A() // This code doesn[ASCII 146]t clean up. { x = new char[10]; // x will be orphaned. throw int(1); } #else A() // This code cleans up fine. { // Initialize automatic variables here. } void Create() { // Initialize dynamic members here. x = new char[10]; throw int(1); } #endif ~A() { delete [] x; } }; void main() { A *a; try { a=0; a=new A; // Do memory allocation in Create() when doing two-phased construction. #ifdef TWO_PHASED_CONSTRUCTION a-