Bir win32 çalıştırılabilir (x86) için, LargeAddressAware bayrağını, x64 Windows üzerinde çalışırken 4 GB'lık bir sanal adres alanına (yalnızca 2 GB yerine) erişebilmesi için ayarlayabilirsiniz.
Bu çok çekici görünüyor. Bununla birlikte, riskler vardır. Örneğin
bkz: Drawbacks of using /LARGEADDRESSAWARE for 32 bit Windows executables?x86 için Birim Testi BüyükAdresAware uyumluluğu
O halde başlayalım ve MEM_TOP_DOWN
sistem çapında kayıt anahtarı AllocationPreference
set ile bazı ünite testleri yapmaktadır sistemi yapılandırmak edelim.
Bu yapılmalı, değil mi?
Yapmıyor!
Sorun, Visual Studio'nun x86 "test çalıştırıcısı" (yürütme altyapısı) LAA'nın kendisinin etkin olmamasıdır.
Bu üst işlem yalnızca "düşük" 2 GB VAS'yi görecek ve modüllerin test edilmesini sağlayacak. VS2013.1
mstest.exe
denÖrnekler Hepsi olan
QTAgent32.exe
vstest.console.exe
yumurtlarvstest.executionengine.x86.exe
çoğaltılır SAA etkin değil!
LAA'nın etkin olduğu bir x86 test yolunu kullanmanın önerilen yolu nedir?
burada SAA yürütme ortamı için kontrol etmek biraz kod parçacığı (VS birim test, csharp) bulunuyor.
sizin test ortamı olduğunu başarılı olmadıkça değil birim testlerinin (ayrıca) SAA ile uyumluluğu kapsayacak sizin kümesine sahip uygun: Bugüne kadar yalnızca Microsoft ikili uğraşmak önerileri rastlamak
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) + ")");
}
}
}
4 GB adres alanı 64 bit sistemlerde geçerli olduğuna dikkat edin. 32 bit sistemlerde, büyük adresli uygulamalar, yalnızca 3 GB'ye hitap edebilir. –
EXE'yi editbin.exe ile düzeltme, yalnızca pragmatik bir çözümdür. –