1

我需要在内存中分配一定的空间,我一直在使用VirtualAlloc它。然而,我越来越注意到VirtualAlloc返回一个超过 32 位的地址,尽管总是小于 33 位。结果是,当我将数据复制到这个内存地址时,计算机会崩溃并蓝屏。

我正在使用 64 位 Windows 和 64 位 Python。我怀疑将数据复制到内存的程序只能处理 32 位。有没有办法强制VirtualAlloc提供 32 位内的地址?

我正在使用Python,特别是ctypes要调用的包VirtualAlloc,请参见下面的代码。多次执行此代码会更改地址,因此重复调用下面的函数最终会导致地址低于 32 位。但是,我正在寻找问题的原因和故障安全解决方案。任何帮助将不胜感激。

import ctypes
mem_commit = 0x1000
page_readwrite = 0x4
size_bytes = 200000  # Allocation sizes are usually around this value

ctypes.windll.kernel32.VirtualAlloc.argtypes = [
    ctypes.c_void_p, ctypes.c_long, ctypes.c_long, ctypes.c_long]
ctypes.windll.kernel32.VirtualAlloc.restype = ctypes.c_int

addr = ctypes.windll.kernel32.VirtualAlloc(
    0, ctypes.c_long(size_bytes), mem_commit, page_readwrite)    

请注意,我之后使用VirtualFree.

4

1 回答 1

0

VirtualAlloc只要在此范围内有足够的可用空间,就可以从 32 位地址内存开始强制执行内存分配。查看msdoc,我们有以下函数签名:

LPVOID VirtualAlloc(
  LPVOID lpAddress,
  SIZE_T dwSize,
  DWORD  flAllocationType,
  DWORD  flProtect
);

以及以下描述lpAddress

要分配的区域的起始地址 [...] 如果此参数为 NULL,则系统确定分配区域的位置。

所以你可以用这个参数选择地址。在您的情况下,您指定 0lpAddress并将其视为 NULL 值。

此外,您必须考虑,如果您选择内存地址,您必须确保空间是空闲的,否则VirtualAlloc不会给您空间。

此外,您使用mem_commitwithoutmem_reserve和 msdoc 说:

尝试通过指定没有 MEM_RESERVE 和非 NULL lpAddress 的 MEM_COMMIT 来提交特定地址范围会失败,除非整个范围已被保留。

更好的选择是使用 0x3000 (MEM_COMMIT|MEM_RESERVE)flAllocationType

最后,您当然可以使用 64 位地址,但在 Windows 上将结果类型设置VirtualAllocc_int和,这是有符号 32 位的别名c_long。因此,返回的 64 位地址VirtualAlloc将被截断,因此您将使用错误的地址来复制数据。

于 2021-05-07T09:14:48.067 回答