Mixing binaries built with different compiler's versions - c++

I would like to know, is calling code placed in a .dll, which was build with a different tool-chain, possible? And is using a .lib file build with an older compiler to build a code with a newer one possible?
I know, the second one is not preferable, but I would like to know, is it impossible.
Precisely my case looks like this:
I have a.exe file built with VC7.1 using b.lib file which was also built with VC7.1 . a.exe calls code from c.dll which was built also using b.dll. Now I want to write a new c.dll, but compile it with VC9. (I want to do so, as I need some libraries which do not provide support for building them with VC7.1 .) -- My c.dll also requires b.lib, still I have sources for it, thus I can recompile it.
So, is it possible to make it work? If not, can you provide a brief explanations, what exactly disallows this?

It is not entirely impossible. The chief problem is that you'll inevitably end up with two distinct copies of the runtime library. Copies that each keep their own state and use their own memory allocator. The DLL interface has to be carefully designed to avoid the possible mishaps that can cause.
Hard rules are that you can never throw an exception from the code in the DLL and catch it in the EXE. And that you cannot return a standard C++ library object like std::string from your DLL code, they have different implementations and the EXE cannot properly destroy the object since it uses a different allocator. And the more general rule, the DLL can never return a pointer to an object that needs to be released by the caller. CRT state can cause subtle problems, like errno not returning the proper error code and locale being set wrong. All and all, plenty of misery that's very hard to diagnose and even harder to fix.
The COM programming model is an example of one that's safe. It never exposes implementation, only pure abstract interfaces. No exceptions, only error codes. Objects are allocated by a factory and reference counted. And where absolutely necessary, it uses a common heap to allocate from, CoTaskMemAlloc(). Not a popular programming model but that's what it takes.

Related

Can a std::string be passed by value across DLL boundries?

Can a std::string be passed by value across DLL boundries between DLLs built with different version of Visual Studio?
No, because templated code is generated separately per module.
So, when your EXE instantiates a std::string and passes it to the DLL, the DLL will begin using a completely different implementation on it. The result is a total mess, but it often sorta almost works because implementations are very similar, or the mess is hard to detect because it's some kind of subtle heap corruption.
Even if they're both built with the same version of VS, it's very precarious / fragile, and I would not recommend it. Either use a C-style interface between modules (for example, COM), or just don't use a DLL.
More detailed explanation here: Creating c++ DLL without static methods
and here: How can I call a function of a C++ DLL that accepts a parameter of type stringstream from C#?
In general, you can not mix binary code built with different compilers, which includes different versions of the same compiler (and can even include the same compiler invoked with different commandline options), so the answer to what you are trying to do is a clear "No".
The reason is that different compilers might provide different implementations of std::string. For example, one implementation could have a fixed, static buffer, while another version doesn't, which already leads to different object sizes. There is a bunch of other things that can make the interfaces incompatible, like the underlying allocator, the internal representation. Some things will already fail to link, due to name mangling or different private APIs, which both protect you from doing something wrong.
Some notes:
Even if you didn't pass the object by value but by reference, the called code could have a different idea of what this objects looks like.
It also doesn't matter that the type is supplied by the compiler, even if you defined the class yourself and compiled two DLLs with different versions of the class definition you would have problems. Also, if you change your standard library implementation, you make your binaries incompatible, too.
It doesn't even matter that the other code is in a DLL, it also applies to code in the same executable or DLL, although headers and automatic recompilation on change make this case very unlikely.
Specifically for MS Windows, you also have a debug heap and a release heap, and memory allocated in one must not be returned to the other. For that reason, you often have two DLL, one with a 'd' suffix (the debug version) and one without. This is a case where the compiler settings already affect compatibility, but you can get around this using a parallel approach of providing two versions of your DLL, too.
To some degree, similar problems occur for C code, too, where compilers have to agree on e.g. struct layout and calling conventions. Due to greater age and lower complexity, different C compilers are effectively compatible though. This is also accepted as a necessary feature in C as opposed to C++.

What problems can appear when using G++ compiled DLL (plugin) in VC++ compiled application?

I use and Application compiled with the Visual C++ Compiler. It can load plugins in form of a .dll. It is rather unimportant what exactly it does, fact is:
This includes calling functions from the .dll that return a pointer to an object of the Applications API, etc.
My question is, what problems may appear when the Application calls a function from the .dll, retrieves a pointer from it and works with it. For example, something that comes into my mind, is the size of a pointer. Is it different in VC++ and G++? If yes, this would probably crash the Application?
I don't want to use the Visual Studio IDE (which is unfortunately the "preferred" way to use the Applications SDK). Can I configure G++ to compile like VC++?
PS: I use MINGW GNU G++
As long as both application and DLL are compiled on the same machine, and as long as they both only use the C ABI, you should be fine.
What you can certainly not do is share any sort of C++ construct. For example, you mustn't new[] an array in the main application and let the DLL delete[] it. That's because there is no fixed C++ ABI, and thus no way in which any given compiler knows how a different compiler implements C++ data structures. This is even true for different versions of MSVC++, which are not ABI-compatible.
All C++ language features are going to be entirely incompatible, I'm afraid. Everything from the name-mangling to memory allocation to the virtual-call mechanism are going to be completely different and not interoperable. The best you can hope for is a quick, merciful crash.
If your components only use extern "C" interfaces to talk to one another, you can probably make this work, although even there, you'll need to be careful. Both C++ runtimes will have startup and shutdown code, and there's no guarantee that whichever linker you use to assemble the application will know how to include this code for the other compiler. You pretty much must link g++-compiled code with g++, for example.
If you use C++ features with only one compiler, and use that compiler's linker, then it gets that much more likely to work.
This should be OK if you know what you are doing. But there's some things to watch out for:
I'm assuming the interface between EXE and DLL is a "C" interface or something COM like where the only C++ classes exposed are through pure-virutal interfaces. It gets messier if you are exporting a concrete class through a DLL.
32-bit vs. 64bit. The 32-bit app won't load a 64-bit DLL and vice-versa. Make sure they match.
Calling convention. __cdecl vs __stdcall. Often times Visual Studio apps are compiled with flags that assuming __stdcall as the default calling convention (or the function prototype explicitly says so). So make sure that the g++ compilers generates code that matches the calling type expected by the EXE. Otherwise, the exported function might run, but the stack can get trashed on return. If you debug through a crash like this, there's a good chance the cdecl vs stdcall convention was incorrectly specified. Easy to fix.
C-Runtimes will not likely be shared between the EXE and DLL, so don't mix and match. A pointer allocated with new or malloc in the EXE should not be released with delete or free in the DLL (and vice versa). Likewise, FILE handles returned by fopen() can not be shared between EXE and DLL. You'll likely crash if any of this happens.... which leads me to my next point....
C++ header files with inline code cause enough headaches and are the source of issues I called out in #3. You'll be OK if the interface between DLL And EXE is a pure "C" interface.
Name mangling issues. If you run into issues where the function name exported doesn't match because of name mangling or because of a leading underscore, you can fix that up in a .DEF file. At least that's what I've done in the past with Visual Studio. Not sure if the equivalent exists in g++/MinGW. Example below. Learn to use "dumpbin.exe /exports" to you can validate your DLL is exporting function with the right name. Using extern "C" will also help fix this as well.
EXPORTS
FooBar=_Foobar#12
BlahBlah=??BlahBlah##QAE#XZ #236 NONAME
Those are the issues that I know of. I can't tell you much more since you didn't explain the interface between the DLL and EXE.
The size of a pointer won't vary; that is dependent on the platform and module bitness and not the compiler (32-bit vs 64-bit and so on).
What can vary is the size of basically everything else, and what will vary are templates.
Padding and alignment of structs tends to be compiler-dependent, and often settings-within-compiler dependent. There are so loose rules, like pointers typically being on a platform-bitness-boundary and bools having 3 bytes after them, but it's up to the compiler how to handle that.
Templates, particularly from the STL (which is different for each compiler) may have different members, sizes, padding, and mostly anything. The only standard part is the API, the backend is left to the STL implementation (there are some rules, but compilers can still compile templates differently). Passing templates between modules from one build is bad enough, but between different compilers it can often be fatal.
Things which aren't standardized (name mangling) or are highly specific by necessity (memory allocation) will also be incompatible. You can get around both of those issues by only destroying from the library that creates (good practice anyway) and using STL objects that take a deleter, for allocation, and exporting using undecorated names and/or the C style (extern "C") for exported methods.
I also seem to remember a catch with how the compilers handle virtual destructors in the vtable, with some small difference.
If you can manage to only pass references of your own objects, avoid externally visible templates entirely, work primarily with pointers and exported or virtual methods, you can avoid a vast majority of the issues (COM does precisely this, for compatibility with most compilers and languages). It can be a pain to write, but if you need that compatibility, it is possible.
To alleviate some, but not all, of the issues, using an alternate to the STL (like Qt's core library) will remove that particular problem. While throwing Qt into any old project is a hideous waste and will cause more bloat than the "boost ALL THE THINGS!!!" philosophy, it can be useful for decoupling the library and the compiler to a greater extent than using a stock STL can.
You can't pass C runtime objects between them. For example you can not open a FILE buffer in one and pass it to be used in the other. You can't free memory allocated on the other side.
The main problems are the function signatures and way parameters are passed to library code. I've had great difficulty getting VC++ dll's to work in gnu based compilers in the past. This was way back when VC++ always cost money and mingw was the free solution.
My experience was with DirectX API's. Slowly a subset got it's binaries modified by enthusiasts but it was never as up-to-date or reliable so after evaluating it I switched to a proper cross platform API, that was SDL.
This wikipedia article describes the different ways libraries can be compiled and linked. It is rather more in depth than I am able to summarise here.

Can changes to a dll be made, while keeping compatibility with pre-compiled executables?

We have a lot of executables that reference one of our dlls. We found a bug in one of our dlls and don't want to have to re-compile and redistribute all of our executables to fix it.
My understanding is that dlls will keep their compatibility with their executables so long as you don't change anything in the header file. So no new class members, no new functions, etc... but a change to the logic within a function should be fine. Is this correct? If it is compiler specific, please let me know, as this may be an issue.
Your understanding is correct. So long as you change the logic but not the interface then you will not run into compatibility issues.
Where you have to be careful is if the interface to the DLL is more than just the function signatures. For example if the original DLL accepted an int parameter but the new DLL enforced a constraint that the value of this parameter must be positive, say, then you would break old programs.
This will work. As long as the interface to the DLL remains the same, older executables can load it and use it just fine. That being said, you're starting down a very dangerous road. As time goes by and you patch more and more DLLs, you may start to see strange behaviour on customer installations that is virtually impossible to diagnose. This arises from unexpected interactions between different versions of your various components. Historically, this problem was known as DLL hell.
In my opinion, it is a much better idea to rebuild, retest, and redistribute the entire application. I would even go further and suggest that you use application manifests to ensure that your executables can only work with specific versions of your DLLs. It may seem like a lot of work now, but it can really save you a lot of headaches in the future.
It depends
in theory yes, if you load the dll with with LoadLibrary and haven't changed the interface you should be fine.
If you OTOH link with the .dll file using some .lib stub there is no guarantee it will work.
That is one of the reasons why COM was invented.

Is it possible to replace the global "operator new()" everywhere?

I would like to replace the global operator new() and operator delete() (along with all of their variants) in order to do some memory management tricks. I would like all code in my application to use the custom operators (including code in my own DLLs as well as third-party DLLs). I have read things to the effect that the linker will choose the first definition it sees when linking (e.g., if the library that contains your custom operator new() is linked first, it will "beat" the link with the CRT). Is there some way to guarantee that this will happen? What are the rules for this, since this really is a multiply-defined symbol (e.g., void* operator new(size_t size) has two definitions in the global namespace)?
What about third-party DLLs that may be statically linked with the CRT? Even if they are dynamically linked with the CRT, is there some way I can get them to link with my operator new()?
The C++ standard explicitly allows you to write your own global operator new and delete (and array variants). The linker has to make it work, though exactly how is up to the implementors (e.g., things like weak externals can be helpful for supplying something if and only if one isn't already present).
As far as DLLs go, it's going to be tricky: a statically linked DLL clearly won't use your code without a lot of extra work. Static linking means it already has a copy of the library code copied into the DLL, and any code in the DLL that used it has the address of that code already encoded. To get around that, you'd have to figure out where the code for new is in the DLL and dynamically patch all the code that calls it to call yours instead).
If the DLL links to the standard library dynamically, it gets only marginally easier -- the import table still encodes the name of the DLL and function in that DLL that provides what it needs. That can be gotten around (e.g. with something like Microsoft's Detours library) but it's somewhat non-trivial (though certainly easier than when the DLL links the standard library statically).
EDIT: After re-reading the question, I realize that your emphasis is on third party components. So in that case the answer is no. There are way too many variables involved.
(Referring to replacing "new" in your own code) The short answer is yes. This is a common trick in systems that do their own memory management. As you may have guessed, it's a very tricky thing to get right, and can easily blow up in your face if you're not careful, but it's certainly plausible and is used by lots of software. (I recall reading through some code that does this in the Doom 3 SDK, for example)
As for replacing new and delete in a 3rd party DLL, that's not going to happen (at least not safely). For one, how do you know that they even use new and delete? Not to mention they may be doing their own variant of this technique and relying on some side effect of it to function properly. And even if you get it working now, how do you know that some future version of that component wont break it? Feel free to muck with your own memory all you want, but for the sake of you and your users sanity, please don't try to micro-manage the memory of other binaries.

Mixing C/C++ Libraries

Is it possible for gcc to link against a library that was created with Visual C++? If so, are there any conflicts/problems that might arise from doing so?
Some of the comments in the answers here are slightly too generalistic.
Whilst no, in the specific case mentioned gcc binaries won't link with a VC++ library (AFAIK). The actual means of interlinking code/libraries is a question of the ABI standard being used.
An increasingly common standard in the embedded world is the EABI (or ARM ABI) standard (based on work done during Itanium development http://www.codesourcery.com/cxx-abi/). If compilers are EABI compliant they can produce executables and libraries which will work with each other. An example of multiple toolchains working together is ARM's RVCT compiler which produces binaries which will work with GCC ARM ABI binaries.
(The code sourcery link is down at the moment but can be google cached)
I would guess not. Usually c++ compilers have quite different methods of name-mangling which means that the linkers will fail to find the correct symbols. This is a good thing by the way, because C++ compilers are allowed by the standard to have much greater levels of incompatibility than just this that will cause your program to crash, die, eat puppies and smear paint all over the wall.
Usual schemes to work around this usually involve language independent techniques like COM or CORBA. A simpler sanctified method is to use C "wrappers" around your C++ code.
It is not possible. It's usually not even possible to link libraries produced by different versions of the same compiler.
No. Plain and simple :-)
Yes, if you make it a dynamic link and make the interface c-style. lib.exe will generate import libraries which are compatible with the gcc toolchain.
That will resolve your linking problems. However that is just the start of the problem.
Your larger problems will be things like exceptions, and memory allocation.
You must ensure that no exception cross from VC++ to gcc code, there are no guarantees of compatibility.
Every object from the VC++ library will need to live on the heap because:
Do not mix gcc new/delete with anything from VC++, bad things will happen. This goes for object construction on the stack too. However, if you make an interface like create_some_obj()/delete_some_obj() you do not end up using gcc new to construct VC++ objects. Maybe make a small handler object that handles construction and destruction. This way you preserve RAII, but still use the c-interface for the true interface.
Calling convention must be correct. In VC++ there is cdecl and stdcall. If gcc tried to call an imported function with the wrong calling type, bad things will happen.
The bottom line is keep a simple interface that is ANSI C compliant, and you should be fine. The fact that crazy C++ goes on behind is okay, as long as it is contained.
Oh and make sure all the code is re-entrant, or you risk opening a whole nother can-o-worms.