Exec compiled with clang-cl loads extra dlls when build

Hello all,

I’m working towards converting an MSVC application to compile and run with Clang-cl.
Over the last years, we’ve make a lot of progress on this.
Today however, I’m facing a problem I don’t understand and hope that you will be able to help me with this.

When I build a single application from a monolithic code base, the executable works. (Thanks a lot for all of the effort to allow this!)

However, if I build all of the executables (and extra dlls), the executable crashes.
From what I can tell, the problem is the following:

  • Exe starts
  • Dll_A gets loaded
  • Dll_A has a dependency on Dll_B
  • Dll_B gets loaded
  • Dll_B depends on Dll_A => Circular dependency

However, when building a single executable, Dll_B was not build and Dll_A doesn’t seem to depend on on Dll_B.

I’ve looked through this with dependency walker and found 2 reasons why Dll_A depends on Dll_B:

Following code exists in the code of Dll_A

class I { virtual I *clone() const = 0; }

class EXPORT Impl { virtual Impl *clone() const { return new Impl{*this}; }

Dependency walker indicates that Dll_A contains:
Impl *Impl::clone() const
It also indicates that Dll_B contains:
I *Impl::clone() const
This last is a bit unexpected to me, however, covariance is not my expertise.

I’ve updated the code to not use covariance just to test.

This again causes a circular dependency, because now a Dll_C (and depends on Dll_B) contains following symbol where Dll_A depends on:
std::allocator::allocator(std::allocator const &)

I wouldn’t even know how to update the MSVC STL, nor would I want to do so as this is an external library.

Do you have any idea on what is causing this and how to get started on creating a reproduction for this? (And no, I unfortunately can’t use CReduce)

Hard to say. Personally, I’ve never used dependency walker (depends.exe?), and I’d approach the problem with dumpbin /imports and dumpbin /dependents. I’d start at the bottom of the dependency graph, gather the lists of imports, and look for major differences. One thing we’ve noticed in the past is that the order of DLLs in /dependents matters for reasons like these.

Regarding the std::allocator constructor, I think that’s expected. Both DLLs are supposed to instantiate the allocator template, and there should be two templates. They aren’t supposed to import from each other, and everything should be fine.

Hey Reid,

It’s indeed depends.exe or a GUI wrapper around it.

I agree that the allocator should be in both DLLs, hence I don’t expect that this second DLL has to be loaded to get the symbol.

I’ll check with dumpbin, hopefully this will lead me to a single CPP file.