Compiler Optimizations - Function has no address - c++

I have not used much pointers to member functions but I think that found some dangerous scenarios when using such pointers.
The problem comes when compiler decides not to assign address to function, because of some optimization. It happened with VS 2015 even in Debug, x86 (with disabled Optimization - /Od). I am refactoring one old system, moving some code in a common static library (common.lib) so to be able to be used from several projects. Even if not the best pattern, the old implementation depends heavily from function member pointers and I do not want to change this. For example, I added the interface ModuleBase to one very big old class to something like:
class ModuleBase
{
public:
typedef void (ModuleBase::*Main)() const; // moved from old module
virtual void FunctionMain() const = 0; // Function has no address, possibly due to compiler optimizations.
virtual void FunctionSecondary() const = 0; // Function has no address, possibly due to compiler optimizations.
};
class OldModule : public ModuleBase
{
public:
virtual void FunctionMain() const {};
virtual void FunctionSecondary() const {};
}
The idea was to move ModuleBase in the Static library, but OldModule to remain in the main EXE project. While ModuleBase was in the main project it worked fine but when I move it in the static Common.lib it start crashing! It took me about 2 days to finally notice that at several places the compiler decided (but only for the Static Library) not to assign addresses to FunctionMain, FunctionSecondary() and etc.. from ModuleBase. So when pointers to these virtual functions were passed to other routines they were zeroes.
For example in the code bellow:
new Manager::ModuleDecription(
"Test Module",
"Secondary Scene",
"Description"
PosX,
PosY,
Proc,
&ModuleBase::FunctionSecondary //contains nullptr when in static library!!!!!
The last member in the structure was zero but only when is in the static library. It was quite nasty because I had to check many other things before to notice this. Also there are other pointers which were not zero because the structure was not zeroed in the constructor so one has to notice that address value is different and crashes when trying to call the function.
So my questions are -
1) Am I seeing this right - is this valid situation (that compiler is removing functions addresses, for the same code when moved in a static library)?
2) How to force compiler always to keep the member function addresses?

My apology, I found no problems with the addresses of pointers-to-members-functions in Visual Studio. Pointers to the base interface virtual functions are resolved Ok, even if placed in a Static Library. Reasons for my problems were:
1) Debugger sometimes shows function addresses of template classes as zeroes
2) Reason for the crashes was that the main project had the /vmg compiler option, but I missed to put it in the Static Library project. In such case one should be careful to use /vmg always in all referenced library projects (complications because of it is another topic).
Anyway, using pointers-to-members functions together with the object pointer is usually a sign of bad underlying design.
I hope this may help someone.

Related

Loading Stages from external code

I wrote a Pipe and Filter based architecture. To avoid confusion the Filter's are called "Stages" in my code. Here's the basic idea :
I want other developers to have the possibility to implement their own Stage class and then I can add it into the list of Stages that already exist at run-time.
I've been reading around for a while and it seems like their are restrictions to dynamic code loading. My current Stage class looks like this :
class Stage
{
public:
void Process();
const uint16_t InputCount();
const uint16_t OutputCount();
void SetOutputPipe(size_t idx, Pipe<AmplitudeVal> *outputPipe);
void SetInputPipe(size_t idx, Pipe<AmplitudeVal> *inputPipe);
protected:
Stage(const uint16_t inputCount, const uint16_t outputCount);
virtual void init() {};
virtual bool work() = 0;
virtual void finish() {};
protected:
const uint16_t mInputCount;
const uint16_t mOutputCount;
std::vector< Pipe<AmplitudeVal>* > mInputs;
std::vector< Pipe<AmplitudeVal>* > mOutputs;
};
AmplitudeVal is simply an alias for float. This class only holds references to pipes it is connected to(mInputs and mOutputs), it doesn't deal with any algorithmic activity. I want to expose as little as I can for ease of use to external developers. Right now this class only relies on the Pipe header and some basic config file. Most examples dealing with loading DLL's propose a class with only pure virtual functions and barely any member variables. I'm not sure what I should do.
I understand you want to have stage in a DLL and have user users derive their work on your DLL.
Scenario 1: consumer and DLL build with same compiler and same standard library
If the consumer uses the same compiler, compatible compiling options, and both, sides use the same shared standard library (default with MSVC), then you solution should work as is
(See related SO question.)
Scenario 2: consumer and DLL build with same compiler but different libraries
If one side uses a different standard library or linking option thereof (for example if you use statically linked library for your DLL and shared library for consumer), then you have to make sure that all objects are ALWAYS created/released on the same side (because DLL and application would each use their own alloaction functions with different memory pools).
This will be very difficult because of:
inheritance of data
virtual destructor
storage management of standard containers (which would be different in DLL and consumer, despite the impression the source code might give that it's the same)
The first step in the right direction would then be to isolate all the data into the private section and ensure clean access via getters and setters. Fortunately, this kind of design is a sound design approach for inheritance, so it's worth to use it even if you don't need it.
Scenario 3: different compilers or incompatible compiling options
If you use different compilers, or incompatible compiling options then the real problems start:
you can't rely on the assumption that both sides have the same understanding of memory layout. So the read/write of members might occur at different locations; a huge mess ! This is why so many DLL classes have no data member. Many also use PIMPL idiom to hide a private memory layout. But PIMPL in this case of inheritance is very similar to using private data (*this would then be the implicit pointer to the private implementation)
the compiler/linker use "mangled" function names. Different compilers might use different mangling, and wouldn't understand each other's symbol definitions (i.e. the client would'nt find SetOutputPipe() despite it's there). This is why most DLL put all member functions as virtual : the functions are called via an offset in a vtable, which uses fortunately the same layout accross compilers in practice.
finally, different compilers could use different calling conventions. But I think in practice on well established platforms, this shouldn't be a major risk
In this answer to a question about DLLs with different compilers (also without inheritance), I've provided some additional explanations and references that could be relevant for such a mixed scenario.
Again using private member data isntead of protected would put you on a safer side. Exposing getters/setters (whether protected or public) using an extern "C" linkage specifier would avoid name mangling issues for non virtual functions.
Final remark:
When exposing classes in libraries, extra-care should be taken to design the class, making data private. This good practice is worth an extra thought, what ever scenario you're in.

c++ plugin : Is it ok to pass polymorphic objects?

When using dynamic libraries, I understand that we should only pass Plain Old Data-structures across boundaries. So can we pass a pointer to base ?
My idea is that the application and the library could both be aware of a common Interface (pure virtual method, = 0).
The library could instantiate a subtype of that Interface,
And the application could use it.
For instance, is the following snippet safe ?
// file interface.h
class IPrinter{
virtual void print(std::string str) = 0;
};
-
// file main.cpp
int main(){
//load plugin...
IPrinter* printer = plugin_get_printer();
printer->print( std::string{"hello"} );
}
-
// file plugin.cpp (compiled by another compiler)
IPrinter* plugin_get_printer(){
return new PrinterImpl{};
}
This snippet is not safe:
the two sides of your DLL boundaries do not use the same compiler. This means that the name mangling (for function names) and the vtable layout (for virtual functions) might not be the same (implementation specific.
the heap on both sides may also be managed differently, thus you have risks related to the deleting of your object if it's not done in the DLL.
This article presents very well the main challenges with binary compatible interfaces.
You may however pass to the other side of the mirror a pointer, as part of a POD as long as the other part doesn't us it by iself (f.ex: your app passes a pointer to a configuration object to the DLL. Later another DLL funct returns that pointer to your app. Your app can then use it as expected (at least if it wasn't a pointer to a local object that no longer exists) .
The presence of virtual functions in your class means that your class is going to have a vtable, and different compilers implement vtables differently.
So, if you use classes with virtual methods across DLL calls where the compiler used on the other side is different from the compiler that you are using, the result is likely to be spectacular crashes.
In your case, the PrinterImpl created by the DLL will have a vtable constructed in a certain way, but the printer->print() call in your main() will attempt to interpret the vtable of IPrinter in a different way in order to resolve the print() method call.

Class conflicts in loaded shared libraries

Say I have a class in my main process:
class MyClass
{
void doStuff();
int myThing;
int mySecondThing;
bool myThirdThing;
};
And I load a shared library, mysharedlib.so, with a newer version of the class compiled in:
class MyClass
{
void doStuff();
int myThing;
int mySecondThing;
bool myThirdThing;
std::string myFourthThing;
u32 myFifthThing;
};
What happens when I create an instance of MyClass / pass existing instances around between the library's functions and the main executable's functions?
I know the two libraries live in a different address space but passing the data between the library and the executable is what confuses me.
Does this behave differently when using gmodule?
Problems might occur when using MyClass objects .
It depends on how you use them.
Take the following scenario (bogus code here).
MyClass* ptr = SharedLibHandle->CreateMyClass();
ptr->doStuffNonVirtual(); //1 this might work fine
ptr->doStuffVirtual(); //2 this will work fine
ptr->myThing= 5; // 3 this might work fine
MyClass* localAllocPtr = new MyClass();
SharedLibHandle()->DoSomethingWithTheClass(localAllocPtr);
...
void DoSomethingWithTheClass(MyClass* ptr)
{
ptr->myFourthThing = " mama " ; // 4 this might seem to work fine
}
In the example above there are several possible use cases based on the place of instantiation and usage :
ptr handles the scenario where the class is instantiated in the so with the size defined in the so , then used by your executable with the size defined there.
localAllocPtr handles the reverse scenario (class instantiated in your executable then passed to .so).
Taking each one :
Call to non virtual function.
Non virtual functions are resolved at compile time, this meaning that if you have a different code implementation inside your executable, the stack pointer will jump to your function implementation instead of the one in the .so . It will work as expected if your code is the same in both of the executable and so , and the structure alignment remains the same (which is most likely).
Call to virtual function
This will work fine, since it will jump into a vftable then jump to the correct memory address in the .so . The .so initialized the class, so offsets, jumps and everything will be legal.
Access of commonly defined member
This will work fine only if myThing has the same alignment inside the structure, meaning he's at *(ptr+0) offset inside the structure. If by any chance inside your class myThing is first and mySecondThing is second, while in the .so mySecondThing is first while myThing is second, then you will change the wrong parameter. Which ironically will have no effect if you continue to use the class inside your executable and not pass it back to the .so (Let's say ignorance is a bliss).
Access to a non-allocated member
When your executable allocs localAllocPtr it will allocate it with the sizeof(MyClass) as defined in your executable. In your executable the class doesn't define a string and a u32. When passing this allocated structure to the .so , the .so will consider the class as having the members and size according to it's definition. When accessing myFourthThing it will access a zone of memory that would normally be *(ptr + 8). If that zone of memory is in use (someone allocated there) you will write outside your ptr bounds into someone else's memory, and it might seem to work fine but you will end up with one of the hardest bugs to find. If after *(ptr +8) nothing is allocated, you'll get lucky and get a segmentation fault.
In order to avoid the sort of problem you are describing a common approach is the pImpl idiom , which allows you to make the class specific implementation private, so you can add virtual functions and member variables while keeping the exposed definition of the class the same.

optimising function pointers and virtual functions in C++

I know a lot of questions on these topics have been asked before, but I have a specific case where speed is (moderately) important and the speed increase when using function pointers rather than virtual functions is about 25%. I wondered (for mostly academic reasons) why?
To give more detail, I am writing a simulation which consists of a series of Cells. The Cells are connected by Links which dictate the interactions between the Cells. The Link class has a virtual function called update(), which causes the two Cells it is linking to interact. It is virtual so that I can create different types of Links to give different types of interactions. For example, at the moment I am simulating inviscid flow, but I may want a link which has viscosity or applies a boundary condition.
The second way I can achieve the same affect is to pass a function pointer to the Link class and make the target of the function pointer a friend. I can now have a non-virtual update() which uses the function pointer. Derived classes can use pointers to different functions giving polymorphic behaviour.
When I build the two versions and profile with Very Sleepy, I find that the function pointer version is significantly faster than the virtual function version and that it appears that the Link class has been entirely optimised away - I just see calls from my main function to the functions pointed to.
I just wondered what made it easier for my compiler (MSVC++ 2012 Express) to optimise the function pointer case better than the virtual function case?
Some code below if it helps for the function pointer case, I'm sure it is obvious how the equivalent would be done with virtual functions.
void InviscidLinkUpdate( void * linkVoid )
{
InviscidLink * link=(InviscidLink*)linkVoid;
//do some stuff with the link
//e.g.
//link->param1=
}
void ViscousLinkUpdate( void * linkVoid )
{
ViscousLink * link=(ViscousLink*)linkVoid;
//do some stuff with the link
//e.g.
//link->param1=
}
class Link
{
public:
Link(Cell *cell1, Cell*cell2, float area, float timeStep, void (*updateFunc)( void * ))
:m_cell1(cell1), m_cell2(cell2), m_area(area), m_timeStep(timeStep), m_update(updateFunc)
~Link(){};
void update() {m_update( this );}
protected:
void (*const m_update)( void *, UNG_FLT );
Cell *m_cell1;
Cell *m_cell2;
float m_area;
float m_timeStep
//some other parameters I want to modify in update()
float param1;
float param2;
};
class InviscidLink : public Link
{
friend void InviscidLinkUpdate( void * linkVoid )
public:
InviscidLink(Cell *cell1, Cell*cell2, float area, float timeStep)
Link(cell1, cell2, area, timeStep, InvicedLinkUpdate)
{}
};
class ViscousLink : public Link
{
friend void ViscousLinkUpdate( void * linkVoid )
public:
ViscousLink(Cell *cell1, Cell*cell2, float area, float timeStep)
Link(cell1, cell2, area, timeStep, ViscousLinkUpdate)
{}
};
edit
I have now put the full source on GitHub - https://github.com/philrosenberg/ung
Compare commit 5ca899d39aa85fa3a86091c1202b2c4cd7147287 (the function pointer version) with commit aff249dbeb5dfdbdaefc8483becef53053c4646f (the virtual function version). Unfortunately I based the test project initially on a wxWidgets project in case I wanted to play with some graphical display so if you don't have wxWidgets then you will need to hack it into a command line project to compile it.
I used Very Sleepy to benchmark it
further edit:
milianw's comment about profile guided optimization turned out to be the solution, but as a comment I currently cannot mark it as the answer. Using the pro version of Visual Studio with the profile guided optimization gave similar runtimes as using inline functions. I guess this is the Virtual Call Speculation described at http://msdn.microsoft.com/en-us/library/e7k32f4k.aspx. I still find it a bit odd that this code could be more easily optimized using function pointers instead of virtual functions, but I guess that is why everyone advises to TEST, rather than assume certain code is faster than another.
Two things I can think about that differs when using function pointers vs virtual functions :
Your class size will be smaller since it won't have a vftable allocated hence smaller size, more cache friendly
There's one indirection less with function pointer ( With virtual functions : Object Indirection, vftable indirection, virtual function indirection , with functors : Object indirection, functor indirection -> your update function is resolved at compile time, since it's not virtual)
As requested, here my comment again as an answer:
Try to use profile-guided optimizations here. Then, the profiler can potentially apply devirtualization to speed up the code. Also, don't forget to mark your implementations as final, which can further help. See e.g. http://channel9.msdn.com/Shows/C9-GoingNative/C9GoingNative-12-C-at-BUILD-2012-Inside-Profile-Guided-Optimization or the excellent GCC article series over at http://hubicka.blogspot.de/search/label/devirtualization.
The actual cost of a virtual function call is normally insignificant. However, virtual functions may, as you observed, impact the code speed considerably. The main reason is that normally a virtual function call is real function call - with adding a frame to the stack. It is so because virtual function calls are resolved in runtime.
If a function is not virtual, it is much easier for C++ compiler to inline it. The call is resolved in compilation time, so the compiler may replace the call with the body of the called function. This allows for much more aggressive optimisations - like doing some computations once only instead of each loop run, etc.
Based on the information provided here my best guess is that you're operating on a large number of objects, and that the one extra indirection induced by the virtual table is increasing cache misses to the point where the I/O to refetch from memory becomes measurable.
As another alternative have you considered using templates and either CRTP or a policy-based approach for the Link class? Depending on your needs it may be possible to entirely remove the dynamic dispatching.

adding virtual function to the end of the class declaration avoids binary incompatibility?

Could someone explain to me why adding a virtual function to the end of a class declaration avoids binary incompatibility?
If I have:
class A
{
public:
virtual ~A();
virtual void someFuncA() = 0;
virtual void someFuncB() = 0;
virtual void other1() = 0;
private:
int someVal;
};
And later modify this class declaration to:
class A
{
public:
virtual ~A();
virtual void someFuncA() = 0;
virtual void someFuncB() = 0;
virtual void someFuncC() = 0;
virtual void other1() = 0;
private:
int someVal;
};
I get a coredump from another .so compiled against the previous declaration. But if I put someFuncC() at the end of the class declaration (after "int someVal"):
class A
{
public:
virtual ~A();
virtual void someFuncA() = 0;
virtual void someFuncB() = 0;
virtual void other1() = 0;
private:
int someVal;
public:
virtual void someFuncC() = 0;
};
I don't see coredump anymore. Could someone tell me why this is? And does this trick always work?
PS. compiler is gcc, does this work with other compilers?
From another answer:
Whether this leads to a memory leak, wipes your hard disk, gets you pregnant, makes nasty Nasal Demons chasing you around your apartment, or lets everything work fine with no apparent problems, is undefined. It might be this way with one compiler, and change with another, change with a new compiler version, with each new compilation, with the moon phases, your mood, or depending on the number or neutrinos that passed through the processor on the last sunny afternoon. Or it might not.
All that, and an infinite amount of other possibilities are put into one term: Undefined behavior:
Just stay away from it.
If you know how a particular compiler version implements its features, you might get this to work. Or you might not. Or you might think it works, but it breaks, but only if whoever sits in front of the computer just ate a yogurt.
Is there any reason why you want this to work anyway?
I suppose it works/doesn't work the way it does/doesn't because your compiler creates virtual table entries in the order the virtual functions are declared. If you mess up the order by putting a virtual function in between the others, then when someone calls other1(), instead someFuncC() is called, possibly with wrong arguments, but definitely at the wrong moment. (Be glad it crashes immediately.)
This is, however, just a guess, and even if it is a right one, unless your gcc version comes with a document somewhere describing this, there's no guarantee it will work this way tomorrow even with the same compiler version.
I'm a bit surprised that this particular rearrangement helps at all. It's certainly not guaranteed to work.
The class you give above will normally be translated to something on this order:
typedef void (*vfunc)(void);
struct __A__impl {
vfunc __vtable_ptr;
int someVal;
};
__A__impl__init(__A__impl *object) {
static vfunc virtual_functions[] = { __A__dtor, __A__someFuncA, __A__someFuncB};
object->__vtable__ptr = virtual_functions;
}
When/if you add someFuncC, you should normally get another entry added to the class' virtual functions table. If the compiler arranges that before any of the other functions, you'll run into a problem where attempting to invoke one function actually invokes another. As long as its address is at the end of the virtual function table, things should still work. C++ doesn't guarantee anything about how vtables are arranged though (or even that there is a vtable).
With respect to normal data, (non-static) members are required to be arranged in ascending order as long as there isn't an intervening access specificer (public:, protected: or private:).
If the compiler followed the same rules when mapping virtual function declarations to vtable positions, your first attempt should work, but your second could break. Obviously enough, there's no guarantee of that though -- as long as it works consistently, the compiler can arrange the vtable about any way it wants to.
Maybe G++ puts its "private" virtual table in a different place than its public one.
At any rate, if you can somehow trick the compiler into thinking an object looks differently than it really does and then use that object you are going to invoke nasal demons. You can't depend on anything they do. This is basically what you are doing.
I suggest avoiding anything related to binary compatibility or serialization with a class. This opens up too many cans of worms and there is not enough fish to eat them all.
When transferring data, prefer XML or an ASCII based protocol with field definitions over a binary protocol. A flexible protocal will help people (including you) debug and maintain the protocols. ASCII and XML protocols offer a higher readability than binary.
Classes, objects, structs and the like, should never be compared as a whole by binary image. The preferred method is for each class to implement its own comparison operators or functions. After all, the class is the expert on how to compare its data members. Some data members, such a pointers and containers, can really screw up binary comparisons.
Since processors are fast, memory is cheap, change your principles from space saving to correctness and robustness. Optimize for speed or space after the program is bug-free.
There are too many horror stories posted to Stack Overflow and the Newsgroups related to binary protocols and binary comparisons (and assignments) of objects. Let's reduce the amount of new horror stories by learning from the existing ones.
Binary compatibility is a bad thing. You should use a plaintext-based system, perhaps XML.
Edit: Misplaced the meaning of your question a little. Windows provides many native ways to share data, for example GetProcAddress, __declspec(dllexport) and __declspec(dllimport). GCC must offer something similar. Binary serialization is a bad thing.
Edit again:
Actually, he didn't mention executables in his post. At all. Nor what he was trying to use his binary compatibility for.