Модульное тестирование для x86 LargeAddressAware совместимость

Для исполняемого файла win32 (x86) мы можем установить флаг LargeAddressAware, чтобы он мог обращаться к виртуальному адресному пространству 4 ГБ (вместо 2 ГБ) при работе в Windows x64.
Это выглядит очень привлекательно. Тем не менее, есть риски.
Например, см .:Недостатки использования / LARGEADDRESSAWARE для 32-битных исполняемых файлов Windows?

Итак, давайте продолжим и настроим систему, которая выполняет некоторыемодульные тесты с общесистемным переключателем реестраAllocationPreference установлен вMEM_TOP_DOWN.
Это должно сделать, не так ли?

Это не так!
Проблема состоит в том, что x86 «тестовый прогон» (механизм выполнения) Visual Studio не включает LAA.
Этот родительский процесс будет видеть только «младшие» 2 ГБ VAS, как и наши модули для тестирования.

Примеры из VS2013.1

mstest.exe нереститсяQTAgent32.exevstest.console.exe нереститсяvstest.executionengine.x86.exe

Все онине LAA включен!

Итак, каков рекомендуемый способ использовать тестер x86 с поддержкой LAA?

Вот небольшой фрагмент кода (модульный тест VS, csharp) для проверки среды выполнения LAA.
если это не удается, ваша тестовая средане подходит для того, чтобы ваш набор юнит-тестов (также) охватывал совместимость с 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) + ")");
        }
    }
}

Ответы на вопрос(1)

Ваш ответ на вопрос