You are not logged in.

#1 2013-08-04 15:50:02

snack
Member
From: Italy
Registered: 2009-01-13
Posts: 673

Destroyer function for a class in C++ plugin: is it really necessary?

I'm toying with run time linking and plugins containing classes in C++. I understand the necessity of a "builder" function defined inside the plugin which returns a pointer to an instance of the plugin class; according to this (see the end of section 3.3) the plugin must also always provide a "destroyer" function which takes care of deleting the object created by the builder, because new and delete could possibly be overloaded for the plugin class thus generating a new/delete mismatch if the object is deleted by the main program with a direct call to delete. It makes sense to me if the delete call is not polymorphic; but here (see the topmost answer) it is stated that the call to delete is polymorphic if the class has a virtual destructor (two excerpts from the C++11 specifications are cited, I don't know it it also applies to C++03).
So I'm a bit confused: is the destroyer function really necessary if my plugin class has a virtual destructor? Or am I completely missing the point here?
Thanks

Offline

#2 2013-08-19 00:28:18

zorro
Member
Registered: 2011-11-18
Posts: 47

Re: Destroyer function for a class in C++ plugin: is it really necessary?

If the destroyers in the hierarchy are non-polymorphic & private and are invoked in the virtual destructors then it seems fine. If the destroyers are non-polymorphic & public, one could be invoked via a base class which would result in a partial destroy. Therefore the destroyers need to be polymorphic.

Offline

#3 2013-08-19 01:34:54

Oxyd
Member
From: Czech Republic
Registered: 2008-01-17
Posts: 162

Re: Destroyer function for a class in C++ plugin: is it really necessary?

You are confusing deallocation with destruction. Let's say you have some foo* p = ...; that was new'd somehow. The expression delete p; does two things:

  1. Invokes the destructor of the object pointed to by p. I.e. it calls p->~foo();. If foo::~foo is virtual, this invokes the correct polymorphic behaviour you described.

  2. Deallocates the memory the object used. delete-expression does this by calling either foo::operator delete(p) or ::operator delete(p).

The problem lies in the second point, not the first one. Let's say your builder uses some other function, let's call it allocate_memory, that is incompatible with delete (or free). To reclaim memory returned by this hypothetical function, you have another hypothetical function, free_memory. The builder could look something like this:

foo* build_foo() {
  void* storage = allocate_memory(sizeof(foo));
  return new (storage) foo;
}

If the client then does foo* p = build_foo(); and later attempts a delete p;, it will not call free_memory but rather ::operator delete(p), which will expect the memory to have been allocated by ::operator new.

As you can see, the issue is completely orthogonal to whichever destructor gets called or how.

Now, if the class foo contained overloads for operators new and delete that invoked allocate_memory and free_memory, and build_foo was just a simple return new foo;, then delete f; on the client side would work just fine because it would invoke foo::operator delete. But that requires the client code to assume something about what build_foo does – namely that it just does a return new foo;.


“UNIX systems generally have a good, though not impeccable, record for software reliability. The typical period between software crashes […] is well over a fortnight of continuous operation.” ~ Dennis M. Ritchie, The UNIX Time-sharing System--A Retrospective

Offline

#4 2013-08-26 12:54:06

snack
Member
From: Italy
Registered: 2009-01-13
Posts: 673

Re: Destroyer function for a class in C++ plugin: is it really necessary?

Thanks Oxyd, the difference between destruction and memory deallocation was clear to me, but indeed your post clarified many many things. The fact here is that I'm designing a plugin architecture, so I'll deal with client code while the users will have to eventually define the memory allocation/deallocation procedures of their plugin classes. To ease their job I prepared a macro which generates the code for the builder function which uses the "new" operator:

#define RegisterSD(sdClassName) \
  G4VSensitiveDetector* sdClassName##Builder(G4String name){ \
    return new sdClassName(name); \
  }

The factory object calls the builder and then passes the built object to a manager class, which will call delete when necessary. If I instruct my users that any eventual redefinition of memory allocation/deallocation routines for plugin classes must be wrapped in overrides of the new and delete operators, then everything should work fine, right? Thanks again.

Offline

Board footer

Powered by FluxBB