Why does build fail in Release mode? - build

I have a C# MVC web app in VS2017 that references two library projects, Crd.Core and Crd.Data. These two libraries both reference the same third party dlls that I've got stored in a folder at the solution level. In Debug everything builds OK. In Release Crd.Core builds OK but Crd.Data fails with two errors:
Unable to generate a temporary class (result=1).
CS0012 The type 'Consilium.TASKMobile.Common.Messages.UserType' is defined in an assembly that is not referenced. You must add a reference to assembly 'Consilium.TASKMobile.Common.Messages, Version=6.0.60037.0, Culture=neutral, PublicKeyToken=null'.
This assembly is definitely referenced. The exact same file is referenced by both projects from the same neutral location. I have tried moving the referenced files, and removing the references before re-adding them again.
The following are the identical for both projects:
configurations (Any CPU)
target framework (4.6.1)
PropertyGroups in the csproj file
References to the thirds party DLLs in the csproj file
Properties of the references (same versions, Copy Local = True, etc)
Basically my two projects are identical in every way that I can think of checking but one of them fails to build in Release mode so there must be something different somewhere. What am I missing? What else can I check?

So I spent quite a bit of time on this and got precisely nowhere so thought I'd take a break and come back to it. Two weeks later I'm preparing to deploy a Release build for my first user testing and lo, no errors!
Apologies to anyone who ends up here looking for a solution - I have no idea what caused it or why the issue went away, suffice to say that neither the dlls or my references to them have changed.

Related

Windows C++ MFC migration: AfxGetThread Assertion. Why does win32u.dll load before mfc140d.dll in some cases?

I have customer code written for Visual Studio 6.0 MFC which has a simple GUI and launches an EXE with arguments. This code was ported from VS6.0 to VS2019 about 2 years ago and works in a production environment on several systems. We now have a new system where the code fails to function... and I'm starting to dig.
The code is throwing exception in appcore.cpp line 196
It is crashing at AfxGetThread() now that I have been able to get VS2019 to find "appcore.cpp".
This is new information.. I will be searching on AfxGetThread next... so this question likely to be a duplicate now.
One difference I have detected is the order where the Visual Studio 2019 debuger loads symbols. I can't say for certain that this is an indication of the actual DLL load order at runtime, but it appears to be. The screenshot below is the SYMBOL load order where a difference is detected between the working and non working instance of the application.
In the image below we have a Tortoise SVN Diff of two ASCII files. One is the DLL symbol load order on the left when the application works. The second is the DLL symbol load order on the right when the application fails to work. Line 7 is the divergance, where in the failig case the library win32u.dll is pulled in before mfc140d.dll.
The customer code uses some Apache log4cxx libraries which I need to investigate, but at this point in the load sequence I'm not 100% sure differences in those libraries or *.h files used at build time could influence the DLL loading order.
So this is the puzzle I'm looking at.
I will include some links to relevant StackOverflow questions that are similar in my search for an answer to this question.
Possibly Useful Links:
https://learn.microsoft.com/en-us/cpp/porting/porting-guide-mfc-scribble?view=msvc-170
The DLLs are searched in order in different locations: Standard Search Order for Desktop Applications
Most likely the DLLs on the failing machine are missing or they are in the wrong location, so Windows grabs something else.
Make sure all the dependencies are installed in the correct folders.
In this case, the crash in appcore.cpp was due to the code having 2 CWinApp derived objects in the code. And the crash occurs at construction time.
The first hurdle is to get VisualStudio2019 to find appcore.cpp and be able to step into this code. I browsed to C:\Program Files(x86)\VisualStudio and searched for "appcore.cpp". This provided the trail of breadcrumbs to get Visual Studio2019 the correct path when it asked for the file.
In my case the path is:
C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.29.30037\atlmfc\src\appcore.cpp
The second hurdle was to put a breakpoint at the ASSERT point, as the FIRST time the program comes up, this ASSERT is OK. At least in my case... the first constructor of the CWinApp object succeeded. So in my case the offensive code which was unexpectadly constructing a CWinApp derived object ran first. Then the second iteration through the ASSERT would happen.
By placing a breakpoint at the ASSERT, you can re-launch and look at the stack trace of the successful object to determine if it's expected or not.
In my case there was a *.h fix required to get ancient Visual Studio 6.0 MFC code to build and link successfully. I don't have the exact secret, but it's essentially getting a *.h to specify the proper WIN_VER minimum windows version before afx.h is included. For the code that failed, an incorrect *.h was included that included the fix PLUS objects that derived CWinApp.
As near as I can tell, the reason this worked on some sites and not others was due to a regression in the code that was built on that particular system.
The other "strange" behavior was that on the system with the bad *.h include the DLL symbol load order was different. I was able to replicate this bad behavior on more than one system running the "bad" Exe code. Then I did the same on working *.exe code. The strange thing was that the "bad" exe had reasonably correct sources in the workspace. So there were source control issues leading to this belief that it worked on one node and not others.
The runtime behavior I was able to catch matched obsolete code committed to source control.

What could possibly "break the debugger" in Visual Studio (maybe std::string?)

Consider setting a breakpoint on the following line, and stepping into it using the Visual Studio debugger (in a fully-cleaned and rebuilt debug build):
Poco::URI testUri( "http://somewhere.com/test/path" );
It turns out this step in will take you to this function:
URI::URI(const char* uri):
_port(0)
{
parse(std::string(uri));
}
And it turns out that when you take a few steps more and pause on the final line after the parse() call, all is well in the newly constructed URI object, specifically:
it has been parsed correctly;
one can expand the this pointer to see correctly assigned member variables (e.g. its_host, _path and _scheme members are set to "somewhere.com", "/test/path" and "http" respectively);
the this pointer at this stage points to a legitimate memory (e.g. 0x002AEE20) location, and at that location one can see what I am confident is the URI object (a set of std::string variables, and one int as it happens).
However, after a single step more, one returns to the original code line, and suddenly:
expanding the testUri object in the "Autos" or "Watch" debugger windows leads to std::string members that cannot be read (there are "errors reading characters of string"), and yet...
the memory where the constructed object resides remains unchanged, and...
the address of testUri is confirmed to point to the unchanged memory
How can this be? Is the VS debugger broken? What broke it?
This is the latest in a sequence of weird issues trying to get POCO Libraries up and going in a multi-threaded MFC project. I have no idea if the MFC or the multi-threading should have any impact on Poco, but I have experienced a week of weirdness -- often with std::string objects involved -- and I'd like to get to the bottom of it. All suggestions for tracing what is occurring greatly appreciated. I'm running VS2015 Community if that make a difference.
As mentioned in the comments, trying to mix different builds (i.e. both release and debug) within the same project can cause issues like this.
In this case, however, it was the mixing of different compilers -- most of the project was built under what seem to be VS2010 conditions, while the Poco libraries were built under VS2015 conditions.
I'm not 100% sure of the conditions under which the wider project was being compiled before, since it was recently upgraded from VS2010 to VS2015, and in the process, the Platform Toolset setting did not show up in the .vcxproj file. I have now (re-)introduced a Platform Toolset for each build configuration and set it to v100, and also rebuilt Poco with the build_vs100.cmd script. Everything seems to work as expected now.
The way I tracked this down was to observe that the application was being compiled with /MDd (multi-threaded debug DLL code generation), yet the linker was attempting to link to the "d" versions of the Poco libraries, not the "mdd" versions. When the compilers were brought into line, the linker correctly linked the "mdd" versions as one would expect.
Since all library linking in Poco is intended to be automatic (see the #pragma directives in PocoFoundation.h), the incorrect library selection was due to changed preprocessor definitions (POCO_STATIC was not being defined). I did not bother to check why this was.

The required DLLs in a visual studio c++ project

I've done some searching and seen questions similar in nature to mine, but none that quite hit the nail on the head of the issue I'm having.
I'm making C++ game in Visual Studio (with the Allegro 5 library) and encountering difficulty running it on other computers. I'm well aware of the 'MSVCR##.dll is missing from this computer' issue, but what I'm wondering is why I'm unable to run my Release build because I'm missing the MSVCR##'D'.dll on a certain computer, when I was under the impression that the 'D' suffixed .dll was exclusively required for running the debugger. I've checked in my configuration manager for release build settings and I have 'Generate Debug Info' set to No, which I thought was the only thing I needed to do. My question I guess is whether or not there are any other settings I need to configure to make sure my Release build isn't looking for the MSVCR##D.dll. Thanks in advance anyone who has any info!
You're a bit confused about the use of the *D libraries. They're indeed used for debug builds, but debug builds differ in multiple ways from release builds. For starters, debug builds by default come with a *.PDB file that contains all the function names (This is your "Generate Debug Info" option). A debugger looks into the .PDB file to find a readable name for a crash site.
Another debug option is to not inline code - this keeps your named functions intact. Inlining may put that single finction inside three other functions, which complicates debugging a bit.
Finally the Debug CRT includes functions that perform extra error checking against bad arguments. Many functions exhibit Undefined Behavior when passed a null pointer, for instance. The Debug libraries will catch quite a few of those, whereas the Release versions assume you pass valid pointers only.
Now DLL's can reference each other; there's a whoel dependency graph. That's why the Dependency Walker tool exists: it figures out which DLL's rqeuire which other DLL's, and this will tell you why you need the *D version.
Thank you very much for all your inputs, I was able to learn a fair bit from this. It turns out the issue was (of course) entirely my fault, as when setting up the Allegro 5 dependencies in the project settings (under General->Linker) I was accidentally including a dependency for the debug version of the Allegro monolith-md.dll as well as the non-debug version in my Release build, and that .dll was in turn referencing the *D version of the MSVCR .dll. The issue has been resolved by removing that dependency from the Release build of my game.
Install dependency walker on that machine. Load the exe. Check if any of the dependent dlls are missing.

How should/could/must I handle the dll that my C++ projects depend on?

I'm lost here and I have no clue how to proceed. This is not a question about how to make my program work, this is a question about how to stop wasting my time.
My programming environment is Visual Studio 2013 on windows, in C++.
I use 3 libraries extensively, namely: boost (using dynamic linking), OpenCV, and Qt.
During the development, I have configured VS to look at those 3 libraries by default for include and .lib. I have also added the 3 folders containing all the dlls to my PATH environment variable.
It works, but it is sometime painful, let me explain you when.
First hassle: Anytime I have a LNK error telling me I miss a function, it is usually on OpenCV since it has only one include file referencing all the functions. I have to look at OpenCV's source code to see what module this function belongs to and to know what I must link my program to.
Second Hassle: When comes the time to deploy my application, I have to ship it with all the relevant dlls. To know which one I need, I open dependency walker and try to forget nothing, I have then to test it on a different computer because 102% of the time I have missed a couple, and then I have to configure my Installer generator to include all those one by one.
Third Hassle: To ease a little bit the process of configuring a new development machine, I have recently switched to NuGet. It is great, I add boost with a couple of clicks to any project. But now my boost DLLs are everywhere, I have one folder per boost library, and since there are dozens of those I can't even add them all at once to my PATH now, so I have to move them manually to the appropriate folder, and that is really not what I want to do with my not-so-precious-but-who-are-you-to-judge time
I have looked around and couldn't find any good practice regarding this issue, maybe because they are too obvious, or too specific to a particular setup.
How do you do? How would you do if you were me?
We put all our external dependencies in version control along with the code. This ensures that all code can build "out of the box" on any of our development machines and also ensures that for any given version of the code, we know exactly which dependencies is has.
The best way to check for missing dependencies is how have a good automated test suite, if you've got comprehensive converge then if your tests pass you must have deployed the required libraries.
In terms of linking to the appropriate libraries, unfortunately, that just sounds like an issue with the structure of OpenCV (I'm not familiar with OpenCV). I tend to use dumpbin under Windows and nm under Linux to easily grep for symbols when I get link errors with an unfamiliar library.

Enable cross-project debugging in VS2010

I have a C/C++ solution comprised of several projects in VS2010. The start-up project is where main() locates and it will generate .exe file, while the others are core algorithms which will generate .dll files. When I debug the whole solution, sometimes it cannot go into the .dll projects but after rebuilding the whole solution, the problem can be temporarily solved; However after building one or more times, the problem returns.
Currently I have to rebuild the whole solution every time I modify the code, but it's so bothering. Is there any way that I can avoid such a problem?
It is happening only in the case when some project in your solution is changed or the .exe present in release or debug directory is different from the code. So, make sure like you are building each project successfully after modifying it.
And it is always good to debug in DEBUG mode to get exact result.
Everal things you could try: Make sure all projects which need to be rebuilt after a change indeed are. So make sure the project dependencies are set correctly and that the startup project is the exe project.
As second option, you could allow the debugger to show source even if it does not match the code exactly (look for something named "source files must match original exactly" or similar in Options->Debugging->General). Be aware that it might indeed happen that your changes are not reflected in the program if this is needed.