ybainier/Hypodermic

Issue when resolving same types in different shared libraries

Closed this issue · 1 comments

Hi!

I've had long running issue in my project in which, when I try to resolve a type in functions from different shared libraries (dylib, I'm running macOS) I have had different results. Steps to repro are:

  • I have executable, library that is dynamically linked and then one that I hot reload
  • In my linked library I have builder which creates a container.
  • In my hot-reloadable library I have builder which I use to register types for nested container
  • After new types have been created I'm resolving some systems

Issue is that If in my hot-reloadable library try to resolve from my container I get completely new instance for all singletons. It is as if comparing of types is not working -- and it isn't. I was looking and TypeAlias, TypeKeyKey and TypeInfo and they use std::type_info. After fast googling it would seem that operating with type_info and type_index are undefined behaviour between different DLLs, so they are not comparable. As it is UB this might not be an issue in all OSs or compilers. I have tested this with this changeset and it fixes my issue as the name of the class is of course same in my whole application. I'm not sure yet of side-effects this might have, but it works great for me.

I then asked ChatGPT if it knows the answer to this and it provided me with following answer (I have no idea if this is correct or not, its ChatGPT):

It is generally not safe to compare typeid of a class in different shared libraries. 
The typeid operator returns a type_info object that provides information about the type of an object. 
This information is implementation-defined, and may be different between different compilers, libraries, or even different versions of the same library.
If you need to compare the types of objects from different shared libraries, you should provide a unique identifier for each type that is guaranteed to be consistent across all libraries. 
This can be achieved by using a unique identifier for each type, such as a string or an integer, and comparing the identifier instead of the typeid.
In C++17 and later, you can use the std::type_index class to compare types across shared libraries. 
The std::type_index class stores a type_info object and provides a hash function that allows you to compare types in a consistent manner across different libraries.

So maybe storing type_index in TypeInfo is the real answer? I'm really not sure. I know my use-case might be a bit niche but it would be great if something similar would be implemented upstream.

EDIT: I did try just storing type_index but it had the original effech: not working

Okei I successfully used this issue as a rubber duck. It seems like, at some point of time, I managed to put my generate_export_header() function and CXX_VISIBILITY_PRESET hidden settings the wrong way around in my cmake config. This caused cmake to generate empty export macro for macOs instead of __attribute__((visibility("default"))). Comparing two typeids when they are not visible to each other seems not work (surprise).

So it was my cmake all along...