Für eine Win32-ausführbare Datei (x86) können wir das LargeAddressAware-Flag festlegen, so dass es auf einen virtuellen Adressraum von 4 GB (statt nur 2 GB) auf x64 Windows zugreifen kann.
Das sieht sehr ansprechend aus. Es gibt jedoch Risiken. siehe
Zum Beispiel: Drawbacks of using /LARGEADDRESSAWARE for 32 bit Windows executables?Unit Testing für x86 LargeAddressAware Kompatibilität
So lassen Sie uns fortfahren und konfigurieren Sie das System, das einige Unit-Tests mit der systemweiten Registrierungsschalter AllocationPreference
Satz MEM_TOP_DOWN
ausgeführt wird.
Das sollte tun, sollte es nicht?
Es tut es nicht!
Das Problem ist, dass der x86 "Test Runner" (Ausführungsengine) von Visual Studio nicht LAA selbst aktiviert ist.
Dieser übergeordnete Prozess sieht nur die "niedrigeren" 2 GB VAS, und so werden unsere Module getestet.
Beispiele aus VS2013.1
mstest.exe
laichtQTAgent32.exe
vstest.console.exe
Spawnsvstest.executionengine.x86.exe
Alle von ihnen sind nicht LAA aktiviert!
Also, was ist die empfohlene Möglichkeit, einen x86 Test Runner zu verwenden, der LAA aktiviert ist?
hier ein kleiner Code-Schnipsel (VS Unit-Test, csharp) für LAA Ausführungsumgebung zu überprüfen.
es sei denn, es gelingt die Testumgebung ist nicht geeignet Ihren Satz von Unit-Tests zu haben (auch) deckt die Kompatibilität mit LAA:
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace TestCheckEnv32LAA
{
[TestClass]
public class CheckEnv32LAA
{
#region [Native DLL import]
[Flags()]
public enum AllocationType : uint
{
COMMIT = 0x1000,
RESERVE = 0x2000,
RESET = 0x80000,
LARGE_PAGES = 0x20000000,
PHYSICAL = 0x400000,
TOP_DOWN = 0x100000,
WRITE_WATCH = 0x200000
}
[Flags()]
public enum MemoryProtection : uint
{
EXECUTE = 0x10,
EXECUTE_READ = 0x20,
EXECUTE_READWRITE = 0x40,
EXECUTE_WRITECOPY = 0x80,
NOACCESS = 0x01,
READONLY = 0x02,
READWRITE = 0x04,
WRITECOPY = 0x08,
GUARD_Modifierflag = 0x100,
NOCACHE_Modifierflag = 0x200,
WRITECOMBINE_Modifierflag = 0x400
}
[StructLayout(LayoutKind.Sequential)]
struct MEMORYSTATUSEX
{
public uint dwLength;
public uint dwMemoryLoad;
public ulong ullTotalPhys;
public ulong ullAvailPhys;
public ulong ullTotalPageFile;
public ulong ullAvailPageFile;
public ulong ullTotalVirtual;
public ulong ullAvailVirtual;
public ulong ullAvailExtendedVirtual;
}
[DllImport("kernel32.dll")]
extern static void GlobalMemoryStatusEx(ref MEMORYSTATUSEX status);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern UIntPtr VirtualAlloc(UIntPtr lpAddress, UIntPtr dwSize,
AllocationType flAllocationType, MemoryProtection flProtect);
#endregion
public CheckEnv32LAA()
{
}
[TestMethod]
public void CheckEnvironment32LAA()
{
// check for a suitable environment to test modules for compatibility with LargeAddressAware (LAA):
// 1) OS must be x64
// 2) test runner must be x86
// 3) test runner must be LAA enabled itself
// 4) memory allocation (with manual TopDown flag) must happen beyond the 2 GB boundary
// 5) memory allocation (with default settings) must happen beyond the 2 GB boundary
//
// RE 3) this requirement is true for "regular" unit tests (to test DLL modules). it does not apply
// for any tests spawning the application (EXE) to be tested as a separate process.
//
// RE 5) a failure indicates the following registry switch has not been set:
// [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management]
// "AllocationPreference"=dword:00100000
//
// see:
// https://stackoverflow.com/questions/2288728/
String sParentProcName = Process.GetCurrentProcess().MainModule.FileName;
//CHECK_1
Assert.IsTrue(Environment.Is64BitOperatingSystem, "Test is not executing on x64 OS");
//CHECK_2
Assert.IsFalse(Environment.Is64BitProcess, "Test runner is not x86: " + sParentProcName);
//CHECK_3
MEMORYSTATUSEX tmpStatus = new MEMORYSTATUSEX();
tmpStatus.dwLength = (uint)Marshal.SizeOf(typeof(MEMORYSTATUSEX));
tmpStatus.ullTotalPhys = 0;
GlobalMemoryStatusEx(ref tmpStatus);
ulong uVM = tmpStatus.ullTotalVirtual;
Assert.IsTrue(uVM > 0x80000000, "Test runner is not LAA enabled (max: " + uVM/(1024 * 1024) + "): " + sParentProcName);
Assert.IsTrue(uVM <= 0x100000000, "Test runner is not x86 (max: " + uVM/(1024 * 1024) + "): " + sParentProcName);
//CHECK_4
UIntPtr pMem = UIntPtr.Zero;
ulong uAddress = 0;
pMem = VirtualAlloc(UIntPtr.Zero, (UIntPtr)1024, AllocationType.RESERVE | AllocationType.TOP_DOWN, MemoryProtection.READWRITE);
uAddress = (ulong)pMem;
Assert.IsTrue(uAddress > 0x80000000, "Test runner is not LAA enabled (highest: " + uAddress/(1024 * 1024) + "): " + sParentProcName);
//CHECK_5
pMem = VirtualAlloc(UIntPtr.Zero, (UIntPtr)1024, AllocationType.RESERVE, MemoryProtection.READWRITE);
uAddress = (ulong)pMem;
Assert.IsTrue(uAddress > 0x80000000, "System-wide MEM_TOP_DOWN is not set (allocated at: " + uAddress/(1024 * 1024) + ")");
}
}
}
Bitte beachten Sie, dass die 4 GB Adressraum auf 64-Bit-Systeme verfügbar ist. Auf 32-Bit-Systemen können große adresssensitive Anwendungen nur 3 GB adressieren. –
Patchen der EXE mit editbin.exe ist die einzige pragmatische Lösung. –