tags:

views:

198

answers:

4

Hi,

Is it safe to use one standard compliant STL in a library, and another in a project that uses that library? For example:

//library.h

#include <string>  //let's say here it uses minGW STL

void Foo(std::string& str_mingw);

//library.cpp
void Foo(std::string& str_mingw) { /*do something*/ }



//application.cpp

#include "library.h"
#include <string>  //let's say here it uses VStudio STL

void Bar()
{
  std::string str_vstudio;
  Foo(str_vstudio);
  //Foo() inside the .lib or .dll uses string from minGW,
  //but here a string from VStudio is used
}

It seems to me that bad things will happen, especially if what is used isn't simple string but something more complicated like tr2::thread. But if so, how can I compile a library in one compiler and let the library users freely choose their preferred compiler for their projects?

+3  A: 

It depends on the library, platform, and how you compile and link it. Often (esp on Windows) libraries are distributed as DLLs, and there are very specific rules about what can be on the boundaries, and how each needs to be compiled.

Boost, for instance, builds DLLs for:

  • single or multithreaded
  • debug or release
  • static (lib) or dynamic (DLL)
  • for each different compiler and version

See http://beta.boost.org/doc/libs/1_36_0/more/getting_started/windows.html#library-naming for the permutations.

So yes, it's a big problem.

Scott Stafford
and doesn't place ANY of them in WinSxS. Bad!
Chris Becke
+6  A: 

Is it safe to use one standard compliant STL in a library, and another in a project that uses that library?

No.

Some parts of STL for reusability are put into a shared library. It is impossible to guarantee that the internal structure of classes would match in the different STLs thus leading to sporadic crashes if both are used by a program interchangeably.

Also note that STLs from different vendors might have different organization of internal namespaces and classes. That has the effect that public symbol std::basic_string might have different internal names and would be mangled differently, making void Foo(std::string& str_mingw); and void Foo(std::string& str_vstudio); from linker perspective two different functions.

Dummy00001
+6  A: 

If - by library - you mean dynamic library - The simple answer is: no and the complex answer is: no.

C++ and dynamic libraries is a very VERY fragile prospect. Any small change requires a rebuild of all modules, and the runtime used by each library MUST be the exact same library instance.

Even if you managed to get a std::string across a dll boundary - while the external interface of std::string is fixed, any implementation differences will make the data appear corrupted.

It is only safe to pass simple POD structs and native data types between dynamic libraries if the runtimes are potentially different - and even then care must be taken to manage object lifetimes correctly - the allocating library MUST be the de-allocating library.

If you mean static library - that doesn't make a huge amount of sense - I dont think that libs made by MinGW will be compatible with MSDev and MSDev libs are incompatible with MinGW. Even should the lib file format be nominally compatible - assuming the different name manglings don't cause prevent a successful ling: the STL library of the final linking environment would be used.

Chris Becke
+1  A: 

Is it safe to use one standard compliant STL in a library, and another in a project that uses that library? ... void Foo(std::string& str_mingw); ... Foo(str_vstudio);

No. It doesn't even have too much to do with dynamic libraries. Even if you managed to somehow link both the MS std::string and the MinGW std::string into the same executable it would still break. You have two separate (likely different) definitions of std::string in your program and if you mix them you are in undefined behavior land.

Note however, that it would work if your std::string is not used in the interface. That is: you can have one library that uses MinGW strings internally and another lib that uses VC strings internally as long as you use const char* (as an example) at the interface level.

Martin