Under what circumstances on Windows can non-incremental linking result in a thrown exception, while incremental linking does not? - visual-c++

I have read that incremental linking and non-incremental linking should be functionally equivalent, but I have recently found a situation where this is not the case, and it's kind of baffling me. It that out that my project's build is unable to explicitly load one DLL (out of many) that contains a wxWidgets GUI element during runtime without incremental linking (/INCREMENTAL) enabled.
To give a little context, I have the following targets built by my project:
main.exe
core.dll
foo.dll
bar.dll
core.dll contains general functions that are used by all other projects. main.exe is a desktop GUI application (using wxWidgets) that explicitly loads foo.dll and bar.dll at runtime via "LoadLibraryW". "GetProcAddress" is then used to request GUI elements from within the DLLs to be displayed, which is all done asynchronously via wxEvent. This has worked as intended for the most part. However, I have found that an issue arises when the main.exe is not incrementally linked.
Specifically, when main.exe is not linked with a core.dll that was linked with /INCREMENTAL, and when my project is implicitly linked to the release build of wxWidgets (which is not incrementally linked), foo.dll crashes at runtime on allocation of a new wxPropertyGrid, or wxPropertyGridManager (have tried both). The exception is thrown within "wxmsw30u_propgrid_vc_x64_custom.dll", which is clearly the property grid DLL. Since the debug version of wxWidgets is incrementally linked and does not crash, I was unable to get further information than this.
That is to say, when using the Release DLL version of wxWidgets, my project works if and only if a core.dll is linked with /INCREMENTAL and then linked into main.exe, regardless of whether or not main.exe is linked incrementally. foo.dll can be linked with a core.dll that was linked with /INCREMENTAL:NO and still be opened correctly by main.exe so long as that condition is satisfied. There are no problems with the Debug DLL version of wxWidgets, which is built with /INCREMENTAL.
That summarizes my specific problem. Since the actual code spans several files long, I've decided to reduce this question to the fundamental problem: how could incremental linking enable what I presume to be a faulty build to run successfully? I'd like some insight into this question in particular since it is truly baffling to me.
EDIT: Specifically, I am using wxWidgets-3.0.4 on Visual Studio 2019 targeting the latest Windows 10 SDK. The machine architecture is x64. I am building the project with CMake and have experienced no such issues on Linux when linking with g++-6.3.0 and using dllopen in place of LoadLibraryW.

Related

Changing compiler from MSVC to clangCL

We have a project, that has lots of dependencies - third party libraries. We get the source code and build them ourselves. Currently we are using MSVC compiler, but looking into transitioning to using clang-cl (so the one installed through Visual Studio installer). We use CMake to generate build files.
I tried rebuilding just the project with clang-cl, but got linking errors (did not find functions of third party libraries). So I imagine ABIs are not compatible. Do I need to rebuild all the libs with clang-cl, Or is there another way? I tried the solution to call vcvarsall.bat like explained on https://clang.llvm.org/docs/UsersManual.html#clang-cl, but got the same linking errors.
What I am basically looking is your experience regarding changing compiler used to build a project.

How to run wxWidgets applications on other machines?

I have downloaded wxWidgets-3.1.0.zip and extracted it to D:\wxWidgets-3.1.0. MY OS: Windows 7 Professional 64 Bit. I am using visual Studio 2015.
I build the library through running: D:\wxWidgets-3.1.0\build\msw\wx_vc14.sln, It was OK. So I can build the projects in samples.
The thing that matters I cannot run this application on another machines where wxWidgets is not installed there. I Don't know Which dlls I must Copy side-by-side my application.
How Can I Also build statically my application so I don not have to copy Dlls?
Can any one add a useful tutorial step by step on how to build on both: Static and dynamic?.
If you open the D:\wxWidgets-3.1.0\samples\minimal\minimal.sln you will be able to see what options you should set. Also, by default, the solution is set to build statically build executable. You can also try to change the "C/C++ -> Code Generation -> RunTime library" in order to statically link the CRT.
If you still need/want the DLL build, at the very least you will need "base" and "core" libraries from D:\wxWidgets-3.1.0\lib\vc_dll folder. And you will also need the CRT libraries. Every time you run the binary, you will get an error on screen that "library such-and-such can't be found". Just copy the library to the same folder where the executable is located.
The other thing - you should've build the library with "Build->Batch Build...->Select All->Build".
HTH.
MSVS 2015 doesn't support linking CRT statically any longer, so you will need to install its CRT DLLs on the target machine in some way. It could be as simple as just copying the DLLs to your application folder (although this is not recommended by Microsoft), but it still needs to be done.
You can build wxWidgets statically simply by choosing the "Release" configuration in the solution file (and not the "DLL Release" one).

Maximum number of statically linked DLLs loaded in MFC application using Visual Studio 2015

My C++ (MFC) application is statically linked and loads a number of statically linked DLLs using LoadLibrary(). All had worked fine using VS2013 but since moving to VS2015 I have seen a number of strange _com_error exceptions being raised in a variety of locations.
In my test setup I have 56 DLLs being loaded and I see these exceptions. If I reduce this to 53 all seems to work fine.
I am assuming it is related to: Working around fls limitations with too many statically linked CRTs?
But what I am wondering is if something specific has changed from VS2013 to VS2015. I note a lot of work has been done on the CRT in this version of Visual Studio (https://blogs.msdn.microsoft.com/vcblog/2015/03/03/introducing-the-universal-crt/)
Note: I am compiling for Vista+ operating systems (_WIN32_WINNT_VISTA)
I can get things to work by recompiling the DLLs to use dynamic linking but was under the impression this is not a good idea if the main application is using static linking (I don't want to change this setting).

Is /nodefaultlib:msvcr100 the proper approach to handling msvcr100.dll vs msvcr100d.dll defaultlib issue

For a cross-platform software project that builds on Linux and Windows we have distinct ways to handle third-party libraries. On Linux we build and link against the versions distributed with the CentOS/RHEL distribution, which means we link against release builds, whereas on Windows we maintain our own third-party library "packages" and on Windows we build two versions of every library - a release version that links msvcr100 and msvcp100 and a debug version that links msvcr100d and msvcp100d.
My question is simply whether it is necessary to build the debug version of the third-party dependencies on Windows or can we simply use /nodefaultlib:msvcr100 when building debug builds of our own software.
A follow up question: Where can I learn about good practices in this regard. I've read the MSDN pages about the msvc runtime, but there is very little there in terms of recommendations.
EDIT:
Let me rephrase the question more concisely. With VS2010, what is the problem with using /nodefaultlib:msvcr100 to link an executable build with /MDd when linking with libraries that are compiled with /MD.
My motivation for this is to avoid to have to build both release and debug version of third party libraries that I use. Also I want my debug build to run faster.
From the document for /MD, /MT, /LD (Use Run-Time Library):
MD: Causes your application to use the multithread- and DLL-specific version of the run-time library. Defines _MT and _DLL and causes the compiler to place the library name MSVCRT.lib into the .obj file.
Applications compiled with this option are statically linked to MSVCRT.lib. This library provides a layer of code that allows the linker to resolve external references. The actual working code is contained in MSVCR100.DLL, which must be available at run time to applications linked with MSVCRT.lib
/MDd: Defines _DEBUG, _MT, and _DLL and causes your application to use the debug multithread- and DLL-specific version of the run-time library. It also causes the compiler to place the library name MSVCRTD.lib into the .obj file.
So there is no documentation for any difference done to the generated code other than _DEBUG being defined.
You only use the Debug build of the CRT to debug your app. It contains lots of asserts to help you catch mistakes in your code. You never ship the debug build of your project, always the Release build. Nor can you, the license forbids shipping msvcr100d.dll. So building your project correctly automatically avoids the dependency on the debug version of the CRT.
The /nodefaultlib linker option was intended to allow linking your program with a custom CRT implementation. Quite rare but some programmers care a lot about building small programs and the standard CRT isn't exactly small.
Some programmers use the /nodefaultlib has a hack around a link problem. Induced when they link code that was built with Debug configuration settings with code built with Release configuration settings. Or link code that has incompatible CRT choices, /MD vs /MT. This can work, no guarantee, but of course only sweeps the real problem under the floor mat.
So no, it is not the proper choice, fixing the core problem should be your goal. Ensure that all your .obj and .lib files are built with the same compiler options and you won't have this problem. If that means that you have to pester a library owner for a proper build then pester first, hack around it only when you've discovered that you don't want to have a dependency on that .lib anymore but don't yet have the time to find an alternative.

Linker warning C++ Visual Studio

I have run into this problem, which although is a warning, I suspect is a sign of something wrong under the hood. When I build in release mode I get this warning:
MSVCRT.lib(cinitexe.obj) : warning LNK4098: defaultlib 'msvcrtd.lib' conflicts with use of other libs; use /NODEFAULTLIB:library
I'm building a dynamic DLL in Visual Studio C++ Express Edition. When I do it in debug mode no warning arises. I've googled a bit and it looks like msvcrt and msvcrtd are both for multithreading, one for debugging and the other not. I could use /NODEFAULTLIB with MSVCRT.lib, but I don't think that avoiding symptoms really helps with the problem.
I really don't know if this is a huge problem. The DLL and .lib files are generated correctly.
Check that your runtime library settings are correct in the Release configuration of your project. Basically it should be the same as your Debug build, but without the word 'Debug' in the description. Visual Studio docs on this issue are here.
Check your settings as follows:
in Solution Explorer right click the Project and select Properties
make sure the Configuration (at the top of the Properties window) is Active (Release)
go to Configuration Properties -> C/C++ -> Code Generation
check that Runtime Library for Release is not a Debug version of the CRT.
The problem is related to your libraries.
They are linked differently than your program.
Your program may be single-threaded, while your libraries may be linked as multithreaded, for example.
Look under
Project Properties
Configuration Properties
C/C++
Code Generation
Runtime Library
to see the setting (e.g. "Multi-threaded Debug DLL (/MDd)").
This is a huge problem, since it can lead to many unexpected crashes of your application, AND you can't distribute an application which links msvcrtd.lib, since you are not allowed to distribute the debug C++ runtimes of Visual Studio.
Though /NODEFAULTLIB should fix those, you should fix the issue itself.
Like casablanca said, msvcrtd.lib is linked in release mode, but it should only be linked in debug mode.
This does not mean that your own application has wrong linker settings. Any of the libraries you use in your project could have incorrect settings as well.
What I usually do to fix this is, to open all the release .lib files which your application links, with a text editor which can open such large binary files (like SciTE), and then I search them for e.g. VC80.DebugCRT (VC80 == Visual Studio 2005 in this case), and if I find this string in one of those libraries, that library should be recompiled with /MD.
If you are linking dynamic libraries, you can use a tool called Dependency Walker on the .dll files instead of manually searching the .lib files.
If Dependency Walker shows the dependency on one of the debug crt DLL files like e.g. MSVCP80D.dll (note the trailing D), recompile that library using /MD.

Resources