|
Prev: Examing an execution, caught by "catch (...)" possible?
Next: C++ Memory Management Innovation: GC Allocator
From: internetpet on 21 Apr 2008 11:43 Say you have these files: BigClazz.h class Clazz; // Note the forward declaration only , no include "Clazz.h" class BigClazz { public: BigClazz(); ~BigClazz(); Clazz* pclazz; }; BigClazz.cpp #include "BigClazz.h" BigClazz::BigClazz(){} BigClazz::~BigClazz() { delete pclazz; // Here the destructor of of the Clazz object will not be called } Clazz.h class Clazz { public: Clazz(); ~Clazz(); }; Clazz.cpp #include "Clazz.h" Clazz::Clazz(){}; Clazz::~Clazz(){}; main.cpp int main(int argc, char *argv[]) { BigClazz* pVM = new BigClazz(); pVM->pclazz = new Clazz(); delete pVM; } If you run this you'll see that the Clazz destructor will not be called when BigClazz does "delete pclazz;" in it's own destructor. But if you replace the forward declaration in BigClazz (class Clazz;) with an include (#include "Clazz.h") then it works. Any idea why? Thanks Eric -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Daniel Krügler on 22 Apr 2008 01:54 On 22 Apr., 04:43, internetpet <internet...(a)hotmail.com> wrote: > BigClazz.h > > class Clazz; // Note the forward declaration only , no include > "Clazz.h" > class BigClazz > { > public: > BigClazz(); > ~BigClazz(); > Clazz* pclazz; > }; > > BigClazz.cpp > > #include "BigClazz.h" > BigClazz::BigClazz(){} > BigClazz::~BigClazz() > { > delete pclazz; // Here the destructor of of the Clazz object > will not be called > } You are violating the constraints of Our Holy Standard here: [expr.delete]/5: "If the object being deleted has incomplete class type at the point of deletion and the complete class has a non-trivial destructor or a deallocation function, the behavior is undefined." > #include "Clazz.h" > Clazz::Clazz(){}; > Clazz::~Clazz(){}; This is a user-defined d'tor, therefore it is non-trivial according to the standard, [class.dtor]/3+4: "If a class has no user-declared destructor, a destructor is declared implicitly. An implicitly-declared destructor is an inline public member of its class. A destructor is trivial if it is an implicitly-declared destructor and [..] Otherwise, the destructor is non-trivial." HTH & Greetings from Bremen, Daniel Kr�gler -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Triple-DES on 22 Apr 2008 01:52 On 22 Apr, 04:43, internetpet <internet...(a)hotmail.com> wrote: > Say you have these files: > > BigClazz.h > > class Clazz; // Note the forward declaration only , no include > "Clazz.h" > class BigClazz > { > public: > BigClazz(); > ~BigClazz(); > Clazz* pclazz; > }; > > BigClazz.cpp > > #include "BigClazz.h" > BigClazz::BigClazz(){} > BigClazz::~BigClazz() > { > delete pclazz; // Here the destructor of of the Clazz object > will not be called > } > > Clazz.h > > class Clazz > { > public: > Clazz(); > ~Clazz(); > }; > > Clazz.cpp > > #include "Clazz.h" > Clazz::Clazz(){}; > Clazz::~Clazz(){}; > > main.cpp > > int main(int argc, char *argv[]) > { > BigClazz* pVM = new BigClazz(); > pVM->pclazz = new Clazz(); > delete pVM; > } > > If you run this you'll see that the Clazz destructor will not be > called when BigClazz does "delete pclazz;" in it's own destructor. But > if you replace the forward declaration in BigClazz (class Clazz;) with > an include > (#include "Clazz.h") then it works. > > Any idea why? Yes. According to [expr.delete]/5 in the standard (with my comments in parens): If the object being deleted has incomplete class type (in this case, forward declared) at the point of deletion and the complete class has a non-trivial destructor (you declared your own dtor, so it's non- trivial) or a deallocation function, the behavior is undefined (which usually means not calling the destructor in this case). To fix this, simply #include "Clazz.h" in BigClazz.cpp, so that the type is complete at the point of deletion. -- DP [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Travis Vitek on 22 Apr 2008 01:53 On Apr 21, 7:43 pm, internetpet <internet...(a)hotmail.com> wrote: > Say you have these files: > > BigClazz.h > > class Clazz; // Note the forward declaration only , no include > "Clazz.h" > class BigClazz > { > public: > BigClazz(); > ~BigClazz(); > Clazz* pclazz; > }; > > BigClazz.cpp > > #include "BigClazz.h" > BigClazz::BigClazz(){} > BigClazz::~BigClazz() > { > delete pclazz; // Here the destructor of of the Clazz object > will not be called > } > <snip> > > If you run this you'll see that the Clazz destructor will not be > called when BigClazz does "delete pclazz;" in it's own destructor. But > if you replace the forward declaration in BigClazz (class Clazz;) with > an include > (#include "Clazz.h") then it works. > > Any idea why? Because the C++ standard allows pointers to incomplete class types to be deleted but if the class has a non-trivial destructor or a class operator delete the behavior is undefined. You can easily work around the problem by including Clazz.h into Bigclazz.cpp so that the type you are deleting is complete at the point you delete it. Travis -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: marlow.andrew on 22 Apr 2008 02:07 On 22 Apr, 03:43, internetpet <internet...(a)hotmail.com> wrote: > Say you have these files: > > BigClazz.h > > class Clazz; // Note the forward declaration only , no include > "Clazz.h" > class BigClazz > { > public: > BigClazz(); > ~BigClazz(); > Clazz* pclazz; > }; > > BigClazz.cpp > > #include "BigClazz.h" > BigClazz::BigClazz(){} > BigClazz::~BigClazz() > { > delete pclazz; // Here the destructor of of the Clazz object > will not be called > } [snip] > If you run this you'll see that the Clazz destructor will not be > called when BigClazz does "delete pclazz;" in it's own destructor. But > if you replace the forward declaration in BigClazz (class Clazz;) with > an include > (#include "Clazz.h") then it works. > > Any idea why? The type must be known for delete blah to be compilable. Hence your code will not compile. Here's the error I got from gcc: BigClazz.cpp: In destructor �BigClazz::~BigClazz()�: BigClazz.cpp:5: warning: possible problem detected in invocation of delete operator: BigClazz.cpp:5: warning: invalid use of undefined type �struct Clazz� BigClazz.h:1: warning: forward declaration of �struct Clazz� BigClazz.cpp:5: note: neither the destructor nor the class-specific operator delete will be called, even if they are declared when the class is defined. Says it all, I think. You wouldn't be using a Micro$oft compiler by any chance? -Andrew Marlow -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
|
Next
|
Last
Pages: 1 2 3 Prev: Examing an execution, caught by "catch (...)" possible? Next: C++ Memory Management Innovation: GC Allocator |