Menu
Visual Studio Code is the first code editor, and first cross-platform development tool - supporting OSX, Linux, and Windows - in the Visual Studio family. At its heart, Visual Studio Code 64 bit features a powerful, fast code editor great for day-to-day use. .NET Core 2.1 is automatically installed when you install Visual Studio for Mac. Creating an ASP.NET Core app in Visual Studio for Mac. Open Visual Studio for Mac. On the Start Screen, select New Project. This will display the New Project dialog, allowing you to select a template to create your application.
![]()
Build Info
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment
March 7th, 2019Visual Studio 2019 Preview 3 introduces a new feature to reduce the binary size of C exception handling (try/catch and automatic destructors) on x64. Dubbed FH4 (for CxxFrameHandler4, see below), I developed new formatting and processing for data used for C exception handling that is 60% smaller than the existing implementation resulting in overall binary reduction of up to 20% for programs with heavy usage of C exception handling. Update 5/25/2019.Due to logistical issues we couldn’t get FH4 turned default on in Update 1. Everything looks in place to have FH4 default on in an early preview of Update 2.fingers crossed.In addition, as Paul reported in the comments below in the Visual Studio 2019 RTM release the new runtime wasn’t being properly installed into system32 with just the Visual Studio installation. That was a general bug in RTM that we’ve since fixed in Update 1, for RTM please run “C:Program Files (x86)Microsoft Visual Studio2019EnterpriseVCRedistMSVC8vcredist.x64.exe” to install the runtime on any machine you plan on running binaries using FH4. Update 7/25/2019.We discovered that hooks used for debugging were missing in the runtime for FH4.
This causes debugger only issues where “step-into” from a throw no longer goes into the corresponding catch and a “step-into” out of the catch no longer goes to the next line in the normal execution path (instead they both go to the next breakpoint/end of program). This has been fixed for 16.2 but due to UWP library turn-around could not make it in time for UWP runtimes in 16.2.
Given that, it was decided to not push FH4 default-on in 16.2 with this known issue but wait for 16.3 where everything will line up. Preview 1 of 16.3 which GA’ed yesterday does have FH4 on by default with the plan to keep it on moving forward. How Do I Turn This On?FH4 is currently off by default because the runtime changes required for Store applications could not make it into the current release. To turn FH4 on for non-Store applications, pass the undocumented flag “/d2FH4” to the MSVC compiler in Visual Studio 2019 Preview 3 and beyond.We plan on enabling FH4 by default once the Store runtime has been updated. We’re hoping to do this in Visual Studio 2019 Update 1 and will update this post once we know more. Tools ChangesAny installation of Visual Studio 2019 Preview 3 and beyond will have the changes in the compiler and C runtime to support FH4. The compiler changes exist internally under the aforementioned “/d2FH4” flag.
The C runtime sports a new DLL called vcruntime1401.dll that is automatically installed by VCRedist. This is required to expose the new exception handler CxxFrameHandler4 that replaces the older CxxFrameHandler3 routine. Static linking and app-local deployment of the new C runtime are both supported as well.Now onto the fun stuff! The rest of this post will cover the internal results from trialing FH4 on Windows, Office, and SQL, followed by more in-depth technical details behind this new technology. Motivation and ResultsAbout a year ago, our partners on the project came to the Microsoft C team with a challenge: how much could we reduce the binary size of C exception handling for programs that heavily used it?In context of a program using, they pointed us to a Windows component Microsoft.UI.Xaml.dll which was known to have a large binary footprint due to C exception handling. I confirmed that this was indeed the case and generated the breakdown of binary size with the existing CxxFrameHandler3, shown below. The percentages in the right side of the chart are percent of total binary size occupied by specific metadata tables and outlined code.I won’t discuss in this post what the specific structures on the right side of the chart do (see James McNellis’s talk on how for more details).
Looking at the total metadata and code however, a whopping 26.4% of the binary size was used by C exception handling. This is an enormous amount of space and was hampering adoption of C/WinRT.We’ve made changes in the past to reduce the size of C exception handling in the compiler without changing the runtime.
This includes dropping metadata for regions of code that cannot throw and folding logically identical states. However, we were reaching the end of what we could do in just the compiler and wouldn’t be able to make a significant dent in something this large.
Analysis showed that there were significant wins to be had but required fundamental changes in the data, code, and runtime. So we went ahead and did them.With the new CxxFrameHandler4 and its accompanying metadata, the size breakdown for Microsoft.UI.XAML.dll is now the following:The binary size used by C exception handling drops by 64% leading to an overall binary size decrease of 18.6% on this binary. ;Notice that:. The magic number has been removed, emitting 0x19930522 every time becomes a problem when a program has thousands of these entries. EHFlags has been moved into the header while dispESTypeList has been phased out due to dropped support of dynamic exception specifications in C17. The compiler will default to the older CxxFrameHandler3 if dynamic exception specifications are used. The lengths of the other tables are no longer stored in “Function Info 4”.
This allows COMDAT folding to fold more of the pointed-to tables even if the “Function Info 4” table itself cannot be folded. (Not explicitly shown) The dispFrame and bbtFlags fields are now variable-length integers. The high-level representation leaves it as an uint32t for easy processing. bbtFlags, dispUnwindMap, dispTryBlockMap, and dispFrame can be omitted depending on the fields set in the header.Taking all this into account, the average size of the new “Function Info 4” structure is now 13 bytes (1 byte header + three 4 byte image relative offsets to other tables) which can scale down even further if some tables are not needed. The lengths of the tables were moved out, but these values are now compressed and 90% of them in Microsoft.UI.Xaml.dll were found to fit within a single byte. In 16.0 and 16.0 Update 1, everything is in place to turn FH4 on for desktop applications. Without the Store runtime available though, we couldn’t enable it on by default because there’s no way to tell if we’re building something that is a Store application or part of one.
My previous statement is saying that with the now GA Update 1 Store support is online alongside Desktop support. Sorry for the confusion.As far as turning this on for production, you should still treat this as being in “preview” rather than release with all the caveats that entails.I originally said in the post that we were hoping for an Update 1 default on but that has since slipped past due to logistics rather than quality of implementation. Everything looks to be good for a preview of Update 2 to have this.fingers crossed. and I’ll make another post once it lands alongside other useful information like what errors can occur if the redistributable isn’t installed correctly. Vcruntime140.dll remains fully binary compatible with all previous DLLs of that name.
All the new functionality exists exclusively in the new vcruntime1401.dll.With every VS update/redistributable run we’ll place the latest version of vcruntime140.dll into system32 but all of them with the same name are by design ABI compatible with each other. So systems with older vcruntime140 will get updated to a functionally identical ABI compatible version and get the new vcruntime1401.dll deployed alongside it when installing Visual Studio 2019. I think the runtime is guaranteed to be only backward compatible, not forward compatible.
I will give an example:If you build the boost libraries with VS 2017 and your main executable with VS 2019, everything should be OK but not vise versa.That means that libraries and executables that are build with VS 2017 are expecting their dependencies to be build with VS 2017 or VS 2015. The same goes for VS 2019 – executables and libraries compiled with it can load their dependencies only if they are(the dependencies) build with VS 2019 or older(VS 2017, VS 2015). Being in the same DLL doesn’t solve the issue. The DLL in 2017 would lack this feature while the one present in 2019 will now have this feature.
![]()
In fact that’s a major reason why it’s not and could not be in the same DLL: an app-local deployment can load in the 2017 DLL that could end up being used by a dependent program that needs the 2019 DLL. Being the same name it would attempt to use the already loaded DLL and fail spectacularly.This isn’t the only feature to break compatibility that we’ve had to take advantage of not requiring forwards compatibility. MSVCP1401.dll was introduced to support additional operations in VS 2017 15.6. I’m trying to do exception handling in native mode (link /subsystem:native). CxxFrameHandler4 uses functions from kernel32, which normally is quite reasonable. However kernel32 isn’t available in native mode.My hope was that SEH would work, but /EHa also uses CxxFrameHandler4.
![]()
I see that there are a number of exported functions in NTDLL.dll with “Exception” in their name, but if they support stack unwinding, I don’t know how to tie into them.There’s a little more information, but in short: If I use /EHa, I get unresolved symbols. If I don’t, my destructors don’t get called.Given the lack of access to kernel32.dll, is there any way for native executables to correctly unwind exceptions in c code? There’s a few layers to this question, so I’m going to try and address them individually.1.
Destructors are a C entity and as such only CxxFrameHandler3/4 can understand them and process them. Without those available they won’t get called regardless of configuration.2. /EHa allows CxxFrameHandler3/4 to interact with SEH exceptions but these functions still need to be present to perform that job. CxxFrameHandler3/4 is what takes care of calling the destructors when unwinding an SEH exception under /EHa and why it’s present even when “only” using SEH exceptions.3.
Given the above 2 points, without kernel32.dll you won’t be able to have C exceptions operate since there’s a chain of dependent functionality from there.That being said, pure SEH unwinding does appear to be available. This can be enforced by not enabling any “/EH” flags and as you observed stops destructors from being generated which removes the reference to CxxFrameHandler3/4. If you want destructor-like behavior then you’ll need to rely on SEH try/finally or similar constructs since the unwinding functionality for C EH is unavailable.
![]() Comments are closed.
|
AuthorWrite something about yourself. No need to be fancy, just an overview. Archives
January 2023
Categories |