Python 在64位计算机上强制执行小于32位的虚拟地址

Python 在64位计算机上强制执行小于32位的虚拟地址,python,memory,ctypes,kernel32,virtualalloc,Python,Memory,Ctypes,Kernel32,Virtualalloc,我需要在内存中分配一定的空间,为此我一直在使用VirtualAlloc。 然而,我越来越注意到,VirtualAlloc返回的地址超过32位,但总是小于33位。 其结果是,当我将数据复制到此内存地址时,计算机会崩溃到BSOD 我使用的是64位windows和64位Python。我怀疑将数据复制到内存的程序只配备了处理32位的功能。是否有一种方法可以强制执行VirtualAlloc以提供32位以内的地址 我正在使用Python,特别是ctypes包来调用VirtualAlloc,请参见下面的代码。

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

我使用的是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

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

LPVOID VirtualAlloc(
  LPVOID lpAddress,
  SIZE_T dwSize,
  DWORD  flAllocationType,
  DWORD  flProtect
);
以及
lpAddress
的以下说明:

要分配的区域的起始地址[…]如果此参数为空,系统将确定在何处分配区域

因此,您可以使用此参数选择地址。在本例中,您为
lpAddress
指定了0,它被视为空值

此外,您必须考虑,如果选择内存地址,则必须确保空间是空闲的或<代码>虚拟ALLUC/不会给您空间。

此外,您使用
mem_commit
而不使用
mem_reserve
,msdoc会说:

尝试通过指定MEM_commit而不使用MEM_RESERVE来提交特定的地址范围时失败,除非已保留整个范围

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


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

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

LPVOID VirtualAlloc(
  LPVOID lpAddress,
  SIZE_T dwSize,
  DWORD  flAllocationType,
  DWORD  flProtect
);
以及
lpAddress
的以下说明:

要分配的区域的起始地址[…]如果此参数为空,系统将确定在何处分配区域

因此,您可以使用此参数选择地址。在本例中,您为
lpAddress
指定了0,它被视为空值

此外,您必须考虑,如果选择内存地址,则必须确保空间是空闲的或<代码>虚拟ALLUC/不会给您空间。

此外,您使用
mem_commit
而不使用
mem_reserve
,msdoc会说:

尝试通过指定MEM_commit而不使用MEM_RESERVE来提交特定的地址范围时失败,除非已保留整个范围

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


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

我认为崩溃是由于传递给“内存复制函数”的
addr
中包含的截断值造成的。请参阅。我认为崩溃是由于传递给“内存复制函数”的
addr
中包含的截断值造成的。看见