Visual Studio 2017 MSVCRT.lib link error

Started by
7 comments, last by SBD 4 years, 10 months ago

Normally something I would follow up on in a Microsoft forum, but thought I'd drop in here first...

I had migrated my project from Visual Studio 2010 to Visual Studio 2017 late last year, and everything went smoothly.  Just recently, however, I was reviving a testing harness I was using for network code and have been encountering a linker error that is slightly befuddling.  Specifically, only in my release builds, I get these:

MSVCRT.lib(delete_array.obj) : error LNK2005: "void __cdecl operator delete[](void *)" (??_V@YAXPEAX@Z) already defined in MSVCRT.lib(delete_array.obj)
MSVCRT.lib(delete_scalar.obj) : error LNK2005: "void __cdecl operator delete(void *)" (??3@YAXPEAX@Z) already defined in MSVCRT.lib(delete_scalar.obj)

Now, normally the first stop in MSVCRT linker errors is to check and make sure all the CRT code generation settings are matching across all libs (Multithreaded DLL, etc.).  I have meticulously checked ALL settings 6 times over to ensure they match.  But then, things are actually a little strange when you consider that in this particular case it's complaining that something in MSVCRT.lib is already defined in...MSVCRT.lib.  That's interesting.

I do have my own overrides for global new and delete, and commenting out the specific ones noted in the link errors does get things linking error-free.  It is worth noting that my overrides are NOT inlined (I guess these days, it's actually not allowed).  Further, why it is *only* those two variants (not the std::nothrow_t variants), and only delete (no issues with the overridden new(s)) is a bit perplexing.  Even more, I am using said overrides/library in many other projects without this issue (and as noted, this was not an issue in this particular project back in Visual Studio 2010).

This smells to me like a Visual Studio 2017 linker issue, but I thought I'd pop in here and see if anyone had seen something similar?

Advertisement

Since it was migrated from VS2010, and since you've already made sure the debug and multithreaded are correct, I'd check for versions of the platform toolset, SDK versions, and every directory setting. If something is using the VS2010 version of the library, and another is the VS2017 version of the library, they'll have errors like that.

You should also review the specific solution files, project files, and property sheets in addition to what Visual Studio shows you, sometimes there are details in the file you may miss in the UI.

Hey frob, thanks for the response.

I had the same thoughts regarding the other settings you mentioned.  Unfortunately, the Target Platform, Windows SDK Version, Platform Toolset, and all of the VC++ directories settings are identical across all of the projects in the solution (and none of which reference anything from VS2010).  In reality, when I somewhat ambiguously said I checked all settings, I meant it quite literally; all General, VC++ Directory, and C/C++ options match across all projects (aside from things which necessarily differ, like PDB output file).  For those who might not know it, a handy feature in VStudio is that you can multi-select projects and open the properties dialog, and just like when you have "All Configurations" or "All Platforms" selected, it will show which properties differ between the projects for the selected configuration(s)/platform(s).

Per your suggestion, I visually inspected the solution and project files, but it didn't reveal anything odd.  I had also inspected the generated command-line for the compiler/linker, and nothing seemed amiss there either.

My gut is telling me that something has gone wrong regarding the weak referencing the linker does for overridden global new/delete, which seems to be borne out by the problem disappearing when I remove my overridden global delete operators (the variants the link error refers to).

Definitely a strange one...I've also opened up a thread with Microsoft, but unless I can extract a repro for them I don't think it'll be much help.

Do you link with any other libraries?

The CRT version must match all static libs, and often must match all DLL's (exceptions are libraries that completely abstract malloc, free, etc.), and I think I have seen some similar things with a static library compiled with a different version or settings (debug/release static/dll/singlethreaded CRT).

1 hour ago, SyncViews said:

Do you link with any other libraries?

The CRT version must match all static libs, and often must match all DLL's (exceptions are libraries that completely abstract malloc, free, etc.), and I think I have seen some similar things with a static library compiled with a different version or settings (debug/release static/dll/singlethreaded CRT).

Hey SyncViews,

There are no external libraries aside from those required by win32 functionality (Iphlpapi.lib, Psapi.lib,Shlwapi.lib, Winmm.lib, Ws2_32.lib).

The most perplexing bit is that it is complaining about something being redefined in the same library, meaning not the usual MSVCRT.lib vs MSVCRTd.lib, etc. (the usual thing caused by CRT mismatches).

I've opened the issue with Microsoft, and was able to get them the info they should need to repro.  I wasn't aware of this, but there is functionality in Visual Studio for generating repro information for linker issues.  You can add "/linkrepro:C:\ReproDir" to your linker command-line and it will dump all the necessary files and info to reproduce the linker phase into the specified directory.  This includes .obj files as well as all .LIBs it is attempting to link.  In looking through this, it confirms that there is only a single CRT lib being included (MSVCRT.lib).

So, we'll see what Microsoft has to say (and I'll update here with results).

For us to investigate this further, could you please provide more details like reproducing steps about this issue and example issue code.we don't know how to reproduce this issue on my side as current description. We look forward to hearing from you!

If we report this link issue to the C++ Team, it is best to provide a Link repro so that we can investigate further.

For link repro:

1. Creat a new diretory, say F:\repro.

2. Add an additional link command line option: “/linkrepro:F:\repro” (When you add this option, please make sure the config you selete in the properties of your project is same with the config you build with).

3. Then rebuild your project.

4. after step #3, F:\repro contains everything we need. You can examine all the files there to see if anything is OK to share.

Also refer to this https://docs.microsoft.com/en-us/cpp/how-to-report-a-problem-with-the-visual-cpp-toolset?view=vs-2017 to get a way to get a repro.

On 5/21/2019 at 2:08 AM, Watson325 said:

For us to investigate this further, could you please provide more details like reproducing steps about this issue and example issue code.we don't know how to reproduce this issue on my side as current description. We look forward to hearing from you!

Hi Watson325, thanks for the response.  I've already raised this issue on the Microsoft support forums, and the compiler team is having a look.

https://developercommunity.visualstudio.com/content/problem/534202/visual-studio-2017-msvcrtlib-link-error.html?childToView=576940#comment-576940

I'll update with the results here when the issue reaches its conclusion.

Just a quick update on this.  I managed to solve the problem by providing the global delete overrides for the new "size" variants introduced in C++14...once I did that the problem disappeared.

However, despite the response I got from the compiler team, I'm not convinced this wasn't an error with the linker.  Full details in the post linked above, but in short, they said "the order in which your overridden global new/delete overrides are linked in can't be guaranteed, so the linker might choose the CRT version later after having already included your overridden version, so you have to put them in their own .obj file and link that in to ensure they always get brought in/searched first."  So their answer was "as designed", and they closed the issue before I could respond again (and haven't replied to my response since then).

I think by the very (C++ standard) definition of global new/delete overriding, defining it "anywhere in the program" means the compiler/linker should always use your provided overrides; in this particular toolchain case (VStudio), specifically, it means MSVCRT*.lib should always be the last place it looks for global new/delete for linking.

Thoughts?

This topic is closed to new replies.

Advertisement