0
votes

Creating a simple Console .NET Core app in Visual Studio 2019 will now default to AnyCPU platform (without Prefer 32-bit set, as it was with a .NET Framework app).

Yet if one toggles on the Prefer 32-bit, the results no longer respect the old logic, whereby an x86 executable would be generated, but instead an x64 is produced.

Some quick code to check:

Console.WriteLine("Initially allocated: {0} bytes", AppDomain.CurrentDomain.MonitoringTotalAllocatedMemorySize);
int noNumbers = 1000000;
object[] objectArray = new object[noNumbers];
Console.WriteLine("Allocated in the end: {0} bytes", AppDomain.CurrentDomain.MonitoringTotalAllocatedMemorySize);

Platform settings (in red) next to the code's output showing the quantity of memory allocated (in orange):

enter image description here

An element inside the object[] array will take 4 bytes on an x86 platform and 8 bytes on an x64 one. The output clearly shows this is x64 code. VMMap also confirms this find, based on the 64-bit virtual addresses visible within the process (green highlight):

enter image description here

One needs to specifically select x86 as platform to get a 32-bit executable:

enter image description here

Is 64-bit output code being generated when setting Prefer 32-bit to enabled in Visual Studio a deliberate change ?

Tested on Visual Studio 2019 16.5 on Windows 10 x64

1
(Aside: You can check if your process is running as 64 bit more easily by accessing Environment.Is64BitProcess)Matthew Watson
The assembly that's generated from you code really does have the option turned on. Something you can verify but running corflags.exe on the generated dll, note how the 32BITPREF flag is turned on. But the issue is that a DLL doesn't lock in the bitness of a process, it is the startup EXE that does it. Very different in .NETCore, it uses a host. Either dotnet.exe or a dedicated one that a VS project generates. The latter follows the platform selection. Dumpbin.exe /headers to see it, Machine type field. Well, that's a bit sloppy.Hans Passant
@CaiusJard: I know that one form the research I performed a while back on how everything comes together, and posted here mihai-albert.com/2019/03/10/net-assembly-cross-bitness-loading, but in .NET Core that no longer applies fully.Mihai Albert
@MatthewWatson: I know that property, and even looked at the exact implementation (same link as in the other comment), but I'm on unfamiliar ground in .NET Core, hence I didn't want to be taken for a ride :) My reasoning was that VMMap won't lie.Mihai Albert

1 Answers

1
votes

As Hans Passant's comment indicated, Visual Studio will build (amongst other files) one .exe - which will disregard the Prefer 32-bit setting completely, and one .dll which will obey the setting (by toggling 32BITPREF).

I got in touch with Microsoft Support, whom in turn talked to the folks in the Visual Studio team. It turns out this is a known thing, and a GitHub issue already exists for removing the Prefer 32-bit altogether for .NET Core projects. In fact, Microsoft Support classified it as a bug.

I've also ran a few tests, and as it stands now, for a .NET Core Console App project, the various platform target settings in Visual Studio will determine the following results for the .exe and .dll respectively:

enter image description here

The full analysis around the file headers and the resulting process' bitness is here.