Re: Returning an unknown number of types/values

From: Jacques Labuschagne (jacques_at_clawshrimp.com)
Date: 01/14/04

  • Next message: Jumbo: "Re: Returning an unknown number of types/values"
    Date: Wed, 14 Jan 2004 19:55:45 +1300
    
    

    Jumbo
    > "Jacques Labuschagne" <jacques@clawshrimp.com> wrote in message
    > news:yJ3Nb.17128$ws.2031755@news02.tsnz.net...
    >
    >>Jumbo
    >>
    >>>I have a few points to make:
    >>>1) I had to remove the code you had inside the derived destructor to get
    >
    > it
    >
    >>>to compile , as the base destructor deletes the memory allocated this
    >
    > seems
    >
    >>>to be ok.
    >>>I'm not sure what you were trying to do with that code.
    >>
    >>There are two steps. The first is calling the T's desctructor, and the
    >>second is freeing the memory. Because you're deleting an array of
    >>unsigned char, the object's destructor won't be called automatically.
    >>My derived destructor compiles on GCC 3.2.3; which compiler are you
    >>using?
    >
    > VSTUDIO.NET I'm using.

    I'm sure this works with VS.Net; I'll give it a try for myself.

    > Honestly I still don't know what you on about with this destructor here's
    > the code you had in the derived destructor:
    > T* t = reinterpret_cast<T*>(buf_);
    > t.~T();
    >
    > You seem to declaring a new object here then asking to delete itself. or
    > smething I dunno what it does. But it honestly doesn't compile here. But
    > anyway why do we need it as when the derived object is destroyed if it's
    > destructor is empty the Base destructor will still clear up the memory by
    > the deleting the memory that was allocated in the derived constructor. So it
    > works fine with and empty derived destructor as far as I can see.

    Consider this example:

         class X{
             public:
             X(): iptr(new int[50]){}
             ~X(){ delete[] iptr; }
             int *iptr;
         };

         Derived<X> d;

    Consider what happens when 'd' is destroyed. If X's destructor is never
    executed, X::iptr will never be freed. When you say
        X* x = new X;
        delete X;
    What's actually happening at the delete step is
        call X::~X(),
        free (sizeof(X)) bytes at &X.
    Base's destructor says something subtly different; it says
        free N unsigned chars.
    That won't free X::iptr, because the memory allocated to it isn't
    within X, it's somewhere else... X::iptr /points/ at that other
    location.
    It is perfectly legal to call the destructor of an object by hand,
    so in Derived's dtor we need to do the following:
         T* t = reinterpret_cast<T*>(buf_);
    That gives us a pointer to buf_. The useful thing about this pointer
    is that *it knows it's a T*. We can then call the destructor of
    the object that has been constructed in buf_, because we have a
    pointer to it.
         t.~T();
    We could also move the delete[] buf_ into the derived destructor if
    we like... If we do that, consider what we have then:
         t.~T();
         delete[] buf_;
    And those are exactly the two steps that have to be performed when
    an object is deleted. To reiterate, we need to manually destruct
    (not just free the memory to) the object we constructed in buf_
    because it is not the same type as an element of buf_.

    >
    >
    >
    > I did some more work and here is my lates code:
    > As you will see I changed the use of bytes to using void pointers and sorted
    > out a few other things:

    The last remaining show-stopper is that one can't copy derived objects
    without leaking memory. You should at least support copying between
    two Derived<T> objects (who have the same type T).

    Jacques


  • Next message: Jumbo: "Re: Returning an unknown number of types/values"

    Relevant Pages

    • Re: C++0x atomic and reference counter
      ... you opt for low-level ordering constraints then you have to specify ... as they cannot legally access the memory locations. ... Does it matter if the destructor is empty as in the example provided? ... and thus needs the acquire fence. ...
      (comp.programming.threads)
    • Re: Virtual dtor and placement new.
      ... // Basically calls the destructor. ... It is possible to store this information in a smart-pointer, ... additional cleanup when the memory is to be deleted (i.e. this functor ...
      (comp.lang.cpp)
    • Re: System.Timers.Timer
      ... I've wrote a class destructor, only when the user enable receiving device status, the destructor is never called and keeps running in memory raising the event ... application terminates successfully ...
      (microsoft.public.dotnet.framework)
    • Re: Virtual dtor and placement new.
      ... templatevoid CallDestructor(T*p) instead of void * helps the ... > could then store a pointer to the original memory and call MyDelete ... The functor is a good solution, but then you don't call the destructor ... unwinded by the compiler. ...
      (comp.lang.cpp)
    • Re: memory leak detection techniques
      ... ExitInstance) rather than waiting for your derived destructor to do it. ... It is a bit of memory which should be used unchanged for the duration of the program, so having the system free it on exit, isn't a disaster. ... [The only time the memory is changed is when someone changes language options: the instruments are unloaded and reloaded with their names in the new language.] ...
      (microsoft.public.vc.mfc)