home bbs files messages ]

Forums before death by AOL, social media and spammers... "We can't have nice things"

   comp.lang.c++.moderated      Moderated discussion of C++ superhackery      33,346 messages   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]

   Message 32,539 of 33,346   
   SG to All   
   Re: Exception in Constructor   
   16 Sep 12 21:29:17   
   
   From: s.gesemann@googlemail.com   
      
   Am Sonntag, 16. September 2012 09:45:32 UTC+2 schrieb Henry:   
      
   > [...]   
   >   
   > class A {   
   > public:   
   > 	A() {   
   > 		m_b = new B(3);   
   > 		throw 0;   
   > 	}   
   > 	~A() {   
   > 		std::cout << __PRETTY_FUNCTION__ << std::endl;   
   > 	}   
   > private:   
   > 	B* m_b;   
   > };   
   >   
   > [...]   
   >   
   > int main() {   
   > 	try {   
   > 		A a;   
   > 	}   
   > 	catch (...) {   
   > 		std::cout << "caught an exception :)" << std::endl;   
   > 	}   
   > 	return 0;   
   > }   
   >   
   > Inside A::A(), I new-ed B and then threw an exception on purpose,   
   > and obviously, A::~A() and B::~B() weren't called.   
   >   
   > It doesn't seems to me that "if a constructor finishes by throwing   
   > an exception, the memory associated with the object itself is   
   > cleaned up — there is no memory leak" is true.   
   >   
   > I am pretty certain that I interpret it incorrectly.  Can someone   
   > elaborate?   
      
   You interpreted it incorrectly.  The FAQ is talking about the   
   sizeof(A) bytes associated with the A-object -- not anything you   
   allocated dynamically yourself inside its constructor. The   
   members/subobjects of A are properly destructed and the memory that   
   would have stored the state of the A-object is properly released --   
   either because it lived in the automatic memory whose scope is left or   
   because the new operator -- considering new A() -- "noticed" the   
   exception and released the memory.   
      
   Since an object is only considered constructed when its constructor   
   finishes successfully, there is nothing to be destructed. So, the dtor   
   won't be called.   
      
   The error in your design is that you want your A to manage a   
   dynamically allocated B using a raw pointer. If you destruct a raw   
   pointer, nothing will happen. So, you basically picked the wrong type   
   (a raw pointer). Try this:   
      
      #include    
      
      ...   
      
      class A   
      {   
      public:   
         A()   
         : m_b(new B(3))   
         { throw 0; }   
      private:   
         std::unique_ptr m_b; // owning pointer   
      };   
      
      int main()   
      {   
        try { new A; }   
        catch (...) {}   
      }   
      
   By the way: I deliberately used new in main just to stress that even   
   this dynamically allocated memory (for the A object) is properly   
   released.   
      
   Cheers!   
   SG   
      
      
   --   
         [ See http://www.gotw.ca/resources/clcm.htm for info about ]   
         [ comp.lang.c++.moderated.    First time posters: Do this! ]   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]


(c) 1994,  bbs@darkrealms.ca