3

I want to call Windows' GetSystemInfo() API function in C# in order to retrieve maximumApplicationAddress and minimumApplicationAddress for scanning the memory of the computer.

I wrote a simple program that outputs these value:

SYSTEM_INFO sys_info = new SYSTEM_INFO();
GetSystemInfo(out sys_info);
Console.WriteLine("Min Address: {0:X}", sys_info.minimumApplicationAddress.ToUInt64());
Console.WriteLine("Max Address: {0:X}", sys_info.maximumApplicationAddress.ToUInt64());

When I run this program, by the debugger(using the Start button), it shows this:

Min Address: 10000
Max Address: 7FFEFFFF

But when I build it, and run the executable file, it shows this:

Min Address: 10000
Max Address: FFFEFFFF

The difference between Max Addresses is a little strange to me. Can you please explain the reason?

Ahmad
  • 5,551
  • 8
  • 41
  • 57
  • 1
    The first one 7FFEFFFF is 2gb, the second one is 4gb. According to [this](http://stackoverflow.com/questions/11891593/the-maximum-amount-of-memory-any-single-process-on-windows-can-address) it may be from this: "32 bit on 64 bit OS: 2 GB, unless set to large address space aware, in which case 4 GB." -- so maybe the debugger is using non-large address aware code but the build version is? – Quantic Sep 13 '16 at 16:19
  • Yes, you are right. According to the linked question, running `editbin /LARGEADDRESSAWARE:NO Program.exe` made the built program act like the debugger – Ahmad Sep 13 '16 at 16:28

2 Answers2

5

It is an implementation detail that should not concern you. You see FFFEFFFF because you are running on a 64-bit operating system and your EXE project's Platform target is set to AnyCPU and the "Prefer 32-bit" option is ticked. The default settings for a .NET project. The AnyCPU option gets the /LARGEADDRESSAWARE option bit in the executable file header set, tells the OS to provide 4 GB of address space on a 64-bit OS. You'll always get 7FFEFFFF on a 32-bit OS.

Set the Platform target to x86 to see the difference. Project > Properties > Build tab.

If you want the Debug build to produce the same value then you need to use Project > Properties > Debugging > untick the "Enable the Visual Studio hosting process" option. The hosting process is another EXE, yourproject.vshost.exe. That it doesn't have the option bit set is, arguably, a bug. But most likely a convenient shortcut for a gritty problem.

You can see the difference between the two with Dumpbin.exe /headers. Reported as "Application can handle large (>2GB) addresses".

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
0

To examine application's address space, it is better to use VirtualQuery or VirtualQueryEx Windows API functions, than to scan the memory page by page (or 64KB region by 64KB region). The Ex variant allows you to examine address space of a process different from yours.

You original question has been answered in the commenct(s) above.

Martin Drab
  • 667
  • 4
  • 6
  • I'm passing values given by `GetSystemInfo()` to `VirtualQueryEx()` to find which pages are assigned to the process – Ahmad Sep 13 '16 at 17:25
  • There is no need to use these addresses at all. Just pass the NULL address to the first `VirtualQueryEx` call. You get a `MEMORY_BASIC_INFORMATION` structure describing the region starting with that address. The structure includes also the size of the region, so in your second call to `VirtualQueryEx`, you pass `NULL + RegionSize` as address value. And so forth. `MEMORY_BASIC_INFORMATION` also informs you about stae of the pages within the region (free, reserved, commited), their protection (read, write, execute) etc. – Martin Drab Sep 13 '16 at 18:20