DECLSPEC_NOVTABLE on pure virtual classes? - c++

This is probably habitual programming redundancy. I have noticed DECLSPEC_NOVTABLE ( __declspec(novtable) ) on a bunch of interfaces defined in headers:
struct DECLSPEC_NOVTABLE IStuff : public IObject
{
virtual method1 () = 0;
virtual method2 () = 0;
};
The MSDN article on this __declspec extended attribute says that adding this guy will remove the construct and desctructor vtable entries and thus result in "significant code size reduction" (because the vtable will be removed entirely).
This just doesn't make much sense to me. These guys are pure virtual, why wouldn't the compiler just do this by default?
The article also says that if you do this, and then try and instantiate one of these things, you will get a run time access violation. But when I tried this with a few compilers (with or without the __declspec extension), they don't compile (as I would have expected).
So I guess to summarize:
Does the compiler strip out the vtable regardless for pure virtual interfaces, or have I missed something fundamental here?
What is the MSDN article talking about ?

The compiler strips out the only reference to the vtable, which would have been during construction of the class. Therefore, the linker can optimize it away since there is no longer a reference in the code to it.
Also by the way, I have made a habit of declaring an empty constructor as protected, and also using Microsoft's extension abstract keyword, to avoid that access violation at runtime. This way, the compiler catches the problem at compile time instead (since only a base class can instantiate the interface through the protected constructor). The derived class will of course fill in the vtable during its construction.

It's a bit of handholding for a dumb compiler/linker. The compiler should not insert any reference to this vtable, as it is quite obvious that there is no need for this vtable. The compiler could also mark the reference in such a way that the linker can eliminate the vtable, but that's more complex of course.

Related

Compile time elimination of virtual tables?

Assuming i have this hierarchy :
class Super
{
public:
virtual void bar();
};
class Sub : public Super
{
public:
virtual void bar() override;
};
is there a way for me to avoid vtables despite using the virtual key word? (curiosity) i have read something about a compiler optimization that eliminates vtables when the object is known during compile time, I'm not really sure, been digging around google for a while, but could't find any answers, so does it mean these?
Sub sb;
sb.bar(); //avoids vtable?
Super& sr = sb;
sr.bar(); //avoids vtable?
Super* srp = &sb;
srp->bar(); //avoids vtable?
One of the gcc developers has a whole series of blog posts about devirtualization. I think he is also active on SO, so there may be a chance that he responses.
However, devirtualization deals mostly with eliminating virtual dispatch by analyzing the program flow and possible types. I don't think it removes the virtual table in general, but there is an example in the second article where a virtual gets inlined and can then be evaluated completely at compile time through constant propagation. In that case, the compiler/linker transformed the program to not use the class at all, and thus it should not contain any object or vtable.
Sub sb;
sb.bar(); //avoids vtable?
The above will never need to use a vtable for dispatch, as the runtime type is known (i.e. it's known to be the same as the compile-time/static type, namely Sub).
Super& sr = sb;
sr.bar(); //avoids vtable?
Super* srp = &sb;
srp->bar(); //avoids vtable?
In these cases, if the pointer/reference and usage appear in the same function, the optimiser may well be smart enough to avoid dispatch via a vtable. If the pointer or reference is passed to some other out-of-line function that migth be called with other types of pointers, then vtable-based dispatch will normally be needed.
More generally, the C++ Standard doesn't make any stipulations about how runtime polymorphism is implemented, so there is no guaranteed, portable way to eliminate "vtables".
That said, your best bets to minimise use of the vtable for dispatch are:
to mark overrides final when the freedom to override further is not actually required, and
to keep the implementation inline (even if implicitly - by having the function implementation in the class definition)
To see if either/both help, you'll have to experiment with or read the docs for your own compiler / tool-chain, optimisation flags etc..
An unused vtable may or may not be removed by the linker: you may want to experiment with cross-object linker optimisation flags if you have multiple translation units.

single virtual inheritance compiler optimization in c++?

If I have this situation in C++ project:
1 base class 'Base' containing only pure virtual functions
1 class 'Derived', which is the only class which inherits (public) from 'Base'
Will the compiler generate a VTABLE?
It seems there would be no need because the project only contains 1 class to which a Base* pointer could possibly point (Derived), so this could be resolved compile time for all cases.
This is interesting if you want to do dependency injection for unit testing but don't want to incur the VTABLE lookup costs in production code.
I don't have hard data, but I have good reasons to say no, it won't turn virtual calls into static ones.
Usually, the compiler only sees a single compilation unit. It cannot know there's only a single subclass, because five months later you may write another subclass, compile it, get some ancient object files from the backup and link them all together.
While link-time optimizations do see the whole picture, they usually work on a far lower-level representation of the program. Such representation allow e.g. inlining of static calls, but don't represent inheritance information (except perhaps as optional metadata) and already have the virtual calls and vtables spelt out explicitly. I know this is the case for Clang and IIRC gcc's whole-program optimizations also work on some low-level IR (GIMPLE?).
Also note that with dynamic loading, you can still add more subclasses long after compilation and LTO. You may not need it, but if I was a compiler writer, I'd be weary of adding an optimization that allows people royally breaking virtual calls in very specific, hard-to-track-down circumstances.
It's rarely worth the trouble - if you don't need virtual calls (e.g. because you know you won't need any more subclasses), don't make stuff virtual. Review your design. If you need some polymorphism but not the full power of virtual, the curiously recurring template pattern may help.
The compiler doesn't have to use a vtable based implementation of virtual function dispatch at all so the answer to your question will be specific to the implementation that you are using.
The vtable is usually not only used for virtual functions, but it is also used to identify the class type when you do some dynamic_cast or when the program accesses the type_info for the class.
If the compiler detects that no virtual functions ever need a dynamic dispatch and none of the other features are used, it just could remove the vtable pointer as an optimization.
Obviously the compiler writer hasn't found it worth the trouble of doing this. Probably because it wouldn't be used very often.

Inheritance in C++ internals

Can some one explain me how inheritance is implemented in C++ ?
Does the base class gets actually copied to that location or just refers to that location ?
What happens if a function in base class is overridden in derived class ? Does it replace it with the new function or copies it in other location in derived class memory ?
first of all you need to understand that C++ is quite different to e.g. Java, because there is no notion of a "Class" retained at runtime. All OO-features are compiled down to things which could also be achieved by plain C or assembler.
Having said this, what acutally happens is that the compiler generates kind-of a struct, whenever you use your class definition. And when you invoke a "method" on your object, actually the compiler just encodes a call to a function which resides somewhere in the generated executable.
Now, if your class inherits from another class, the compiler somehow includes the fields of the baseclass in the struct he uses for the derived class. E.g. it could place these fields at the front and place the fields corresponding to the derived class after that. Please note: you must not make any assumptions regarding the concrete memory layout the C++ compiler uses. If you do so, you're basically on your own and loose any portability.
How is the inheritance implemented? well, it depends!
if you use a normal function, then the compiler will use the concrete type he's figured out and just encode a jump to the right function.
if you use a virtual function, the compiler will generate a vtable and generate code to look up a function pointer from that vtable, depending on the run time type of the object
This distinction is very important in practice. Note, it is not true that inheritance is allways implemented through a vtable in C++ (this is a common gotcha). Only if you mark a certain member function as virtual (or have done so for the same member function in a baseclass), then you'll get a call which is directed at runtime to the right function. Because of this, a virtual function call is much slower than a non-virtual call (might be several hundered times)
Inheritance in C++ is often accomplished via the vtable. The linked Wikipedia article is a good starting point for your questions. If I went into more detail in this answer, it would essentially be a regurgitation of it.

Does an abstract classes have a VTABLE?

Do we have virtual table for an abstract class?
First of all, usage of vtables is implementation defined and not mandated by the standard.
For implementations that use vtable, the answer is: Yes, usually. You might think that vtable isn't required for abstract classes because the derived class will have its own vtable, but it is needed during construction: While the base class is being constructed, it sets the vtable pointer to its own vtable. Later when the derived class constructor is entered, it will use its own vtable instead.
That said, in some cases this isn't needed and the vtable can be optimized away. For example, MS Visual C++ provides the __declspec(novtable) flag to disable vtable generation on pure interface classes.
There seems to be a common misconception here, and I think traces of its sources can still be found online. Paul DiLascia wrote sometime in 2000 that -
...see that the compiler still
generates a vtable all of whose
entries are NULL and still generates
code to initialize the vtable in the
constructor or destructor for A.
That may actually have been true then, but certainly isn't now.
Yes, abstract classes do have vtables, also with pure abstract methods (these can actually be implemented and called), and yes - their constructor does initialize the pure entries to a specified value. For VC++ at least, that value is in the address of the CRT function _purecall. You can in fact control that value, either by overloading purecall yourself or using _set_purecall_handler.
We have a virtual table for a class which has atleast one virtual function.
that virtual function can also be pure.
this means. an abstact class can have a vtable.
in case of abstact classes the vtable entry will be NULL.
when ever you try to instantiate a abstract class it will check in tha vtable and check for a NULL value is present or not.
if NULL is present the compiler will throw an error.

COM-like interfaces warn about non virtual destructor

Is there a way to tell gcc that the abstract class it's compiling does not need a virtual destructor (like COM-objects never have)? For example nsISupports always complains about the missing virtual destructor. Turning off the warning would not help as I may have non-COM-like classes, where I want this warning.
So __attribute__((com_interface)) is deprecated and changed only the vtable layout. Is there another __attribute__ where I can tell the compiler that I don't want to be warned about the missing destructor on this class?
The missing virtual dtor warning is there for a reason - mainly because it's a debugging nightmare to track down, especially in a large and complex code base
You may have a very specific reason for doing this but ask yourself, what happens if a class gets refactored such that it's usage changes later down the line?
I think you should re-consider disabling this warning. It's there for a reason. Not putting a virtual destructor in your class may be correct today, but you cannot predict exactly how your class will be used in the future.
A subtle change in the way the class is used could lead to the next developer pulling their hair out for hours trying to track down a resource leak. Do that person a favor and make the destructor virtual now.
Also you may want to ask yourself
What do I gain by making it non-virtual
You mentioned having an abstract class so I assume it has at least a single virtual function. So making the destructor virtual doesn't add a v-table to the object, it just merely extends it to include another member.
I can't see any real gain in making this non-virtual. Only problems.
You probably want to use a pair of diagnostic pragmas. Failing that, #pragma GCC system_header disables all warnings in a given file.