I've come with problems using shared libraries (.dll in Win 10).
I build a lib called xlib in two different configurations, and try to test use them via CMake in a project called xlibtest.
the work flow is:
Step A. build xlib => xlib.dll + xlib.lib(only symbol) + xlib.pdb[optional]
Step B. build xlibtest and link xlib.lib => xlibtest.exe
If build configuration is different in Step A and Step B, then when I'm running xlibtest.exe, there will be problems. For example, I have a function
//xlib.h
void foo(std::string input);
in xlib, it will crash when I call this function.
//xlibtest.cpp
int main() {
xlib::foo("test"); // in debug mode I found the string pass to foo is wrong
}
I've searched and found some explanation about this problem. It may because of the difference in memory pattern of debug and release configuration. And a suggestion is not mix these two configurations, i.e. use debug lib in debug configuration and release lib in release configuration.
Then here is the problem. I can build two version of my own library. However what can I do for those external libraries?
I've used intel MKL libraries in my project, and linking the same libraries in both debug and release configuration. It seems works fine.
But when I'm using Boost libraries, there may be difference between debug and release version, since we can decide the version we build when install Boost libraries.
P.S. The reason why I don't link with static libraries is that there is error is compile time and requires same configuration (i.e. debug/release).
--Update--
I'm using:
CMake 3.5.2;
Compiler: Intel icl 16.0 update 3 for Intel 64 VS2015 environment;
IDE: VS 2015 Community;
OS: Windows 10, 64 bit.
CPU: Intel i7 4930K
Sorry for not providing these information about the tool chain. I used to thought this is a general problem without relation to the tool chain I use. @Hans Passant
I think answer from @John D may end my confusion. After I learnt there are problem in mixing debug and release configuration, I can't understand why there is no difference in using Intel MKL libs, that's why I post this question. Is it the reason that Intel MKL lib is a C lib that has no std::string in it?
Technically, "Debug" and "Release" builds of a library are builds with different compiler switches and preprocessor macros. It's not fundamentally different from, say, compiling a library with optional features.
DEBUG
macro enables chunks of code with various runtime checks and diagnostics. The latter may include adding members to data types.So, Debug and Release versions of C++ code that you build are, in the general case, binary incompatible.
This stands for the code of the C++ standard library. Although it's typically not compiled from stratch each time but one of the few precompiled versions are inserted (including a "thunk" version that delegates to a DLL).
Problems will occur if you have two modules that
The problem predominantly occurs in dynamic linking (but might happen in static linking too if, say, a pre-built static library doesn't correspond to its headers).
This happens if the modules have been compiled (to use the problematic type) and linked (to use library code working with the problematic type) against binary incompatible versions of the library defining that type.
So, specifically for the C++ standard library, to avoid and/or fix those, you need to
libgcc
) - e.g. it may be required for exceptions to pass between them. If your environment is so heterogeneous that it's impossible to achieve, it may be wise to forfeit C++ types as an exchange format altogether.(to specify correct ones and name your own modules so that they can be distinguished)
At link time (static or dynamic), there's no such thing as "build configurations". All there is are a number of modules. All the linker sees is references to other modules (dynamic linking only) and exported/imported entries. And all it does is find the referenced modules (again, dynamic only; in static, the modules are typically specified explicitly), then match exported and imported entries together. C++ export/import entry names contain the entire signature of the entry in encoded ("mangled") form (specifically, incompatible compilers have to use different mangling schemes so entries produced by them don't clash.
The only ways for the linker to distinguish two versions of the library are:
3) isn't generally practical (requires lots of boilerplate code) and in dynamic linking , is unusable without 2) 'cuz a linker first matches module names. 1) (search paths flavor) doesn't scale.
To summarize:
_d
suffix, version suffix)