对于Win32可执行文件(x86),我们可以设置LargeAddressAware标志,以便在x64 Windows上运行时可以访问4 GB(而不是2 GB)的虚拟地址空间。
这看起来很吸引人。但是,存在风险。
例如,查看:Drawbacks of using /LARGEADDRESSAWARE for 32 bit Windows executables?

因此,让我们继续并配置执行某些单元测试的系统,并将系统范围的注册表开关AllocationPreference设置为MEM_TOP_DOWN
那应该做,不是吗?

不会!
问题是Visual Studio的x86“测试运行程序”(执行引擎)本身未启用LAA。
此父进程将仅看到“较低”的2 GB VAS,因此将要测试我们的模块。

VS2013.1中的示例

  • mstest.exe生成QTAgent32.exe
  • vstest.console.exe生成vstest.executionengine.x86.exe

  • 所有这些都未启用LAA!

    那么,推荐使用启用了LAA的x86测试运行器的方法是什么?

    这是一个用于检查LAA执行环境的小代码段(VS单元测试,csharp)。
    除非它成功,否则您的测试环境是,而不适合,因此不适合让您的单元测试集涵盖与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) + ")");
            }
        }
    }
    

    最佳答案

    到目前为止,我只是碰到了要弄混问题中列出的Microsoft二进制文件的建议(即使用editbin.exe手动“修补”它们)。但这具有以下缺点:

  • 一旦为Visual Studio安装了任何将来的Service Pack,我就需要重复修补程序
  • 我不能再并行测试:LAA
  • 的“常规” x86和“扩展” x86

    看来微软必须实现适当的长期解决方案?
    http://visualstudio.uservoice.com/forums/196039-microsoft-test-tools/suggestions/5781437

    关于windows - x86 LargeAddressAware兼容性的单元测试,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23114068/

    10-11 22:35
    查看更多