0

I was performing research into some issues with a C++ library and ensuring type information is consistent between the application and the shared object. I'm also interested in ensuring an EqualObject comparison works, meaning I indeed have the same object, and not two objects that happen to be equal under operator==.

This answer state to anchor a vtable in a header. I'm not familiar with the technique. Or I've heard it called by another name.

What is vtable anchoring, and how does it work?


I'm also aware of dynamic_cast, throw, typeid don't work with shared libraries from the GCC FAQ.

Community
  • 1
  • 1
jww
  • 97,681
  • 90
  • 411
  • 885

1 Answers1

1

It's non-standard technology, but the problem is fairly clear: Which Translation Unit should contain the vtable? If a virtual destructor isn't inlined, it is defined in exactly one Translation Unit, and it's an easy choice to put the vtable there.

For portable code, this is pretty irrelevant. You wouldn't care about duplicate vtables.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • Thanks MSalter. *"...it [the dtor] is defined in exactly one Translation Unit..."* - so does that mean header-only source files should have a implementation file added just to ensure the dtor is defined out-of-line in one translation unit? Or maybe the out-of-line dtor should be provided in an existing implementation file? (I think one of them is what the answer is stating). – jww Jan 21 '16 at 14:57
  • To continue the comment... The answer also goes on to say: *"... defining a virtual out-of-line destructor (it must be the first virtual function declaration in the header)..."* - what is the significance of making the dtor the first virtual function? If the dtor is the first virtual function in a base class, then can derived classes put it anywhere? Or do derived classes also have to list the dtor as the first virtual function, too? (I've never seen this requirement before, and I am having a hard time wrapping my head around it because I don't understand what it accomplishes). – jww Jan 21 '16 at 15:00
  • @jww: Now I'm confused. How did you suddenly end up with header-only ? I thought you had an actual C++ shared library? The "dtor as first virtual function" helps make things more predictable: it eliminates the difference between compilers that put the vtable in the TU defining the first virtual function and those which put the vtable in the TU defining the dtor (both are unique, but could be different). If this is all confusing, it's because it's mostly an implementation detail for compiler makers. Proper portable C++ code doesn't even assume there's a vtable to start with! – MSalters Jan 21 '16 at 16:02
  • *"How did you suddenly end up with header-only"* - yes, its always been that way (or in many cases, yes). *"I thought you had an actual C++ shared library?"* - yes. *"Proper portable C++ code doesn't even assume there's a vtable to start with"* - yes, agreed. But we support back to GCC 3.0 (Fedora 1 is a test platform), so we have to be careful about what we do because we are tied to compiler personalities. – jww Jan 21 '16 at 16:19
  • The reason for this research and hair splitting is a (1) we need to know if we can compare objects and ensure we are comparing the actual allocated object, and (2) a warning on a compiler-provided, non-virtual destructor; calling ***`delete`*** through a base class pointer; and how to address it. The use case for (1) is kind of annoying - it has to do with NIST business requirements; it has nothing to do with C++ other than to complicate matters. The library is [Crypto++](https://www.cryptopp.com/). – jww Jan 21 '16 at 16:20
  • @jww: (1) is philosophical in the extreme. Two objects are the same in C++ when their addresses are the same. But the compiler has almost infinite freedom under the as-if rule. (2) is just a matter of "don't do that, it's Undefined Behavior". Per C++11, you can declare the default dtor private, and still get the compiler-provided implementation. (`private: ~Foo()=default;`) – MSalters Jan 21 '16 at 16:30
  • I also see that you have a rather unusual definition of "header-only". In normal C++ parlance, it explicitly means "Does not come with a (shared) library". This is typical for fully templated code. – MSalters Jan 21 '16 at 16:33
  • @MSalters My rule of thumb for classes is that if I need multiple translation units for the class's definitions to make things manageable I should break the class up. Haven't spent much time worrying about where to put (non-inline) virtual function definitions since I decided upon that as I tend to prefer not including function definitions in declarations even for short functions due to the possibility of adding things that would make them non-trivial (though I haven't yet taken to the pimpl pattern for full acceptance of that methodology). – JAB Feb 05 '16 at 23:35