Runtime Issues While Mixing Libraries from Differe

2019-02-14 07:11发布

问题:

I have encountered an unexpected Access Error while running a project I've built using two different versions of Visual Studio. My general configuration is as follows:

  • LibA is a static lib, static runtime linkage, msvc 8.0
  • LibB is a static lib, static runtime linkage, msvc 9.0
  • My target project for integration is a msvc 9.0 COM dll, which statically links the above libraries

This project builds, but crashes up at runtime with an access violation in some STL code. The stack seems to indicate that I've passed through headers both versions (8 and 9) during a call into a stream insertion operator. I realize that this is a problem.

Somehow, this call:

ost << std::dec << port_; //(originating from an object in LibA)

...descends through the following stack trace:

std::basic_ostream::operator<<(...) (ostream:283, msvc 8.0 version <-- expected, since LibA was built with this version)
std::num_put::put(...) (xlocnum:888, msvc 8.0 version <-- expected, since LibA was built with this version)
std::num_put::do_put(...) (xlocnum:1158, msvc 9.0 version!! !@#$!%! <-- not expected, since LibA was built with msvc 8.0)
std::ios_base::flags() (xiosbase:374, msvc 9.0 version <-- follows from above)

The access violation happens in std::ios_base::flags(). I suspect it is due to the mix of implementations in the call stack (although I am not sure).

My questions are.

1.) Is the likely cause of this access violation the mixing of msvc header implementations?
2.) Is there a way to prevent these implementations from mixing?
3.) Is there a better way to configure these three projects for integration (assuming moving LibA from msvc 8.0 is undesirable)?

I am aware of the ideas raised in this question and this one. Here I am most interested in this specific problem, and if there is some way to avoid it.

Any insights would be appreciated.

回答1:

You can't use different STL implementation in the same project. This means even different versions from the same compiler. If your LibA has a function that accepts std::vector as an argument you are only allowed to pass vector object from STL that LibA was built with. This is why many C++ libraries expose only C API.

Either you change your API or you rebuild all your projects using the same compiler.

You are doing something that you shouldn't. You are in the world of undefined behavior. There is no point in trying to debug this particular crash. Even if you managed to make this line work you would get a new crash somewhere else.



回答2:

There is no guarantee of library binary compatibility between major versions of MSVC. STL code is mostly template code that gets expanded into your code. So you're static libraries probably have incompatible chunks of STL code inside of them.

In general, this shouldn't be a problem, unless that STL code is part of the interface to the library. For example, if you pass iterators or a reference to a vector from one library to another, you're in trouble.

The best solution is to build everything with the same version of the compiler. If you can't do that (e.g., if the one of the libraries is from a third-party), you're probably stuck.