PYTHON - Ctypes : OSError: exception: access violation writing 0xFFFFFFFFFA1C001B
PYTHON - Ctypes : OSError: exception: access violation writing 0xFFFFFFFFFA1C001B
这是使用内存映射将值写入内存的代码。当我尝试 运行 代码时,出现错误
"File "MMF.py”,第 26 行,在
memcpy(pBuf, szMsg, len(szMsg))
OSError:异常:访问冲突写入 0xFFFFFFFFFA1C001B
import msvcrt, mmap
import ctypes
from ctypes import *
FILE_MAP_ALL_ACCESS = 0x04
INVALID_HANDLE_VALUE = 0xFFFFFFFF
SHMEMSIZE = 256
PAGE_READWRITE = 0x04
szName = ctypes.c_wchar_p("MyFileMappingObject")
szMsg = "Message from Python(ctypes) process"
hMapObject = windll.kernel32.CreateFileMappingA(INVALID_HANDLE_VALUE,None, PAGE_READWRITE, 0, SHMEMSIZE, szName)
print("Handle:",hMapObject)
if (hMapObject == 0):
print("Could not open file mapping object")
raise WinError()
pBuf = windll.kernel32.MapViewOfFile(hMapObject, FILE_MAP_ALL_ACCESS,0, 0, SHMEMSIZE)
print("Buffer Starting Addr:",pBuf)
if (pBuf == 0):
print("Could not map view of file")
raise WinError()
else:
print(len(szMsg))
memcpy = cdll.msvcrt.memcpy
memcpy(pBuf, szMsg, len(szMsg))
shmem = mmap.mmap(0, 256, "MyFileMappingObject_ctypes", mmap.ACCESS_WRITE)
shmem.write("Message Python process")
msvcrt.getch()
windll.kernel32.UnmapViewOfFile(pBuf)
windll.kernel32.CloseHandle(hMapObject)
shmem.close()
首先,这里(几乎)是您需要的一切:[Python 3.Docs]: ctypes - A foreign function library for Python。 ctypes.wintypes就不解释了,但是可以在Python[=中通过运行dir(ctypes.wintypes)
看到它的导出107=] 控制台。请注意,所有这些类型都是简单的 CTypes 类型,我使用它们只是为了约定/一致性/可读性。
您更新后的代码(code00.py):
import sys
import ctypes as ct
import ctypes.wintypes as wt
import mmap
import msvcrt
def main(*argv):
FILE_MAP_ALL_ACCESS = 0x000F001F
INVALID_HANDLE_VALUE = -1
SHMEMSIZE = 0x100
PAGE_READWRITE = 0x04
kernel32_dll = ct.windll.kernel32
msvcrt_dll = ct.cdll.msvcrt # To be avoided
CreateFileMapping = kernel32_dll.CreateFileMappingW
CreateFileMapping.argtypes = (wt.HANDLE, wt.LPVOID, wt.DWORD, wt.DWORD, wt.DWORD, wt.LPCWSTR)
CreateFileMapping.restype = wt.HANDLE
MapViewOfFile = kernel32_dll.MapViewOfFile
MapViewOfFile.argtypes = (wt.HANDLE, wt.DWORD, wt.DWORD, wt.DWORD, ct.c_ulonglong)
MapViewOfFile.restype = wt.LPVOID
memcpy = msvcrt_dll.memcpy
memcpy.argtypes = (ct.c_void_p, ct.c_void_p, ct.c_size_t)
memcpy.restype = wt.LPVOID
RtlCopyMemory = kernel32_dll.RtlCopyMemory
RtlCopyMemory.argtypes = (wt.LPVOID, wt.LPCVOID, ct.c_ulonglong)
UnmapViewOfFile = kernel32_dll.UnmapViewOfFile
UnmapViewOfFile.argtypes = (wt.LPCVOID,)
UnmapViewOfFile.restype = wt.BOOL
CloseHandle = kernel32_dll.CloseHandle
CloseHandle.argtypes = (wt.HANDLE,)
CloseHandle.restype = wt.BOOL
GetLastError = kernel32_dll.GetLastError
file_mapping_name_ptr = ct.c_wchar_p("MyFileMappingObject")
msg = "Message from Python(ctypes) process"
msg_ptr = ct.c_wchar_p(msg)
mapping_handle = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, SHMEMSIZE, file_mapping_name_ptr)
print("Mapping object handle: 0x{:016X}".format(mapping_handle))
if not mapping_handle:
print("Could not open file mapping object: {:d}".format(GetLastError()))
raise ct.WinError()
mapped_view_ptr = MapViewOfFile(mapping_handle, FILE_MAP_ALL_ACCESS, 0, 0, SHMEMSIZE)
print("Mapped view addr: 0x{:016X}".format(mapped_view_ptr))
if not mapped_view_ptr:
print("Could not map view of file: {:d}".format(GetLastError()))
CloseHandle(mapping_handle)
raise ct.WinError()
byte_len = len(msg) * ct.sizeof(ct.c_wchar)
print("Message length: {:d} chars ({:d} bytes)".format(len(msg), byte_len))
memcpy(mapped_view_ptr, msg_ptr, byte_len) # Comment this line
RtlCopyMemory(mapped_view_ptr, msg_ptr, byte_len)
# Python vriant
shmem = mmap.mmap(0, 256, "MyFileMappingObject_ctypes", mmap.ACCESS_WRITE)
shmem.write(b"Message Python process")
print("Hit a key to clean all memory maps and exit...")
msvcrt.getch()
UnmapViewOfFile(mapped_view_ptr)
CloseHandle(mapping_handle)
shmem.close()
if __name__ == "__main__":
print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(item.strip() for item in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform))
main(*sys.argv[1:])
print("\nDone.")
备注:
为函数添加了 argtypes 和 restype。详情可见“指定所需参数类型(函数原型)”和“Return类型”部分,以及课程 MS.Docs for function declarations. This is Undefined Behavior (UB) especially on 64bit:
memcpy 的 2nd 参数是一个 Python 字符串,它 not 与它的 char * 地址相同(更不用说在Python 3,字符串是 wchar_t 基础的)memcpy 期望的,这可能还会产生 UB
常数:
FILE_MAP_ALL_ACCESS的值是0x000F001F(从[=49=打印出来的值]VStudio 2015), 0x04对应FILE_MAP_READ
将 INVALID_HANDLE_VALUE 的旧值转换为 HANDLE 时出错,将其更改为 -1 (如 handleapi.h)
您正在使用 c_wchar_p 调用 CreateFileMappingA。这将为映射对象设置一个仅包含提供的字符串中的第 1st 个字符的名称,因为每个 wchar_t 包含 2 bytes: 0x00 加上相应的 char 值 - 'A' 将表示为 0x00 0x41(通常这是 not true - 特别是 0x00 部分,但在我们的例子中,它是) - 所以lpName 参数中的 2nd char (由于 little-endianness) 将是 0x00 (NUL)
根据上面的页面:
Accessing the standard C library through cdll.msvcrt
will use an outdated version of the library that may be incompatible with the one being used by Python.
因此,我还添加了 [MS.Docs]: RtlCopyMemory function to replace memcpy (you can comment out its line, I left it there just to show that it works), as in the example ([MS.Docs]: Creating Named Shared Memory),您从中获取了代码,并尝试对其进行转换 ([minwinbase.h: #36]: #define CopyMemory RtlCopyMemory
)
已将命名约定更改为 Python 兼容 ([Python]: PEP 8 -- Style Guide for Python Code)
其他(非关键)更改(输出格式、移动代码行以获得更好的结构等等...)
输出:
[cfati@CFATI-5510-0:e:\Work\Dev\Whosebug\q048788549]> "e:\Work\Dev\VEnvs\py_pc064_03.07.06_test0\Scripts\python.exe" code00.py
Python 3.7.6 (tags/v3.7.6:43364a7ae0, Dec 19 2019, 00:42:30) [MSC v.1916 64 bit (AMD64)] 64bit on win32
Mapping object handle: 0x000000000000022C
Mapped view addr: 0x00000192912B0000
Message length: 35 chars (70 bytes)
Hit a key to clean all memory maps and exit...
Done.
这是使用内存映射将值写入内存的代码。当我尝试 运行 代码时,出现错误 "File "MMF.py”,第 26 行,在 memcpy(pBuf, szMsg, len(szMsg)) OSError:异常:访问冲突写入 0xFFFFFFFFFA1C001B
import msvcrt, mmap
import ctypes
from ctypes import *
FILE_MAP_ALL_ACCESS = 0x04
INVALID_HANDLE_VALUE = 0xFFFFFFFF
SHMEMSIZE = 256
PAGE_READWRITE = 0x04
szName = ctypes.c_wchar_p("MyFileMappingObject")
szMsg = "Message from Python(ctypes) process"
hMapObject = windll.kernel32.CreateFileMappingA(INVALID_HANDLE_VALUE,None, PAGE_READWRITE, 0, SHMEMSIZE, szName)
print("Handle:",hMapObject)
if (hMapObject == 0):
print("Could not open file mapping object")
raise WinError()
pBuf = windll.kernel32.MapViewOfFile(hMapObject, FILE_MAP_ALL_ACCESS,0, 0, SHMEMSIZE)
print("Buffer Starting Addr:",pBuf)
if (pBuf == 0):
print("Could not map view of file")
raise WinError()
else:
print(len(szMsg))
memcpy = cdll.msvcrt.memcpy
memcpy(pBuf, szMsg, len(szMsg))
shmem = mmap.mmap(0, 256, "MyFileMappingObject_ctypes", mmap.ACCESS_WRITE)
shmem.write("Message Python process")
msvcrt.getch()
windll.kernel32.UnmapViewOfFile(pBuf)
windll.kernel32.CloseHandle(hMapObject)
shmem.close()
首先,这里(几乎)是您需要的一切:[Python 3.Docs]: ctypes - A foreign function library for Python。 ctypes.wintypes就不解释了,但是可以在Python[=中通过运行dir(ctypes.wintypes)
看到它的导出107=] 控制台。请注意,所有这些类型都是简单的 CTypes 类型,我使用它们只是为了约定/一致性/可读性。
您更新后的代码(code00.py):
import sys
import ctypes as ct
import ctypes.wintypes as wt
import mmap
import msvcrt
def main(*argv):
FILE_MAP_ALL_ACCESS = 0x000F001F
INVALID_HANDLE_VALUE = -1
SHMEMSIZE = 0x100
PAGE_READWRITE = 0x04
kernel32_dll = ct.windll.kernel32
msvcrt_dll = ct.cdll.msvcrt # To be avoided
CreateFileMapping = kernel32_dll.CreateFileMappingW
CreateFileMapping.argtypes = (wt.HANDLE, wt.LPVOID, wt.DWORD, wt.DWORD, wt.DWORD, wt.LPCWSTR)
CreateFileMapping.restype = wt.HANDLE
MapViewOfFile = kernel32_dll.MapViewOfFile
MapViewOfFile.argtypes = (wt.HANDLE, wt.DWORD, wt.DWORD, wt.DWORD, ct.c_ulonglong)
MapViewOfFile.restype = wt.LPVOID
memcpy = msvcrt_dll.memcpy
memcpy.argtypes = (ct.c_void_p, ct.c_void_p, ct.c_size_t)
memcpy.restype = wt.LPVOID
RtlCopyMemory = kernel32_dll.RtlCopyMemory
RtlCopyMemory.argtypes = (wt.LPVOID, wt.LPCVOID, ct.c_ulonglong)
UnmapViewOfFile = kernel32_dll.UnmapViewOfFile
UnmapViewOfFile.argtypes = (wt.LPCVOID,)
UnmapViewOfFile.restype = wt.BOOL
CloseHandle = kernel32_dll.CloseHandle
CloseHandle.argtypes = (wt.HANDLE,)
CloseHandle.restype = wt.BOOL
GetLastError = kernel32_dll.GetLastError
file_mapping_name_ptr = ct.c_wchar_p("MyFileMappingObject")
msg = "Message from Python(ctypes) process"
msg_ptr = ct.c_wchar_p(msg)
mapping_handle = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, SHMEMSIZE, file_mapping_name_ptr)
print("Mapping object handle: 0x{:016X}".format(mapping_handle))
if not mapping_handle:
print("Could not open file mapping object: {:d}".format(GetLastError()))
raise ct.WinError()
mapped_view_ptr = MapViewOfFile(mapping_handle, FILE_MAP_ALL_ACCESS, 0, 0, SHMEMSIZE)
print("Mapped view addr: 0x{:016X}".format(mapped_view_ptr))
if not mapped_view_ptr:
print("Could not map view of file: {:d}".format(GetLastError()))
CloseHandle(mapping_handle)
raise ct.WinError()
byte_len = len(msg) * ct.sizeof(ct.c_wchar)
print("Message length: {:d} chars ({:d} bytes)".format(len(msg), byte_len))
memcpy(mapped_view_ptr, msg_ptr, byte_len) # Comment this line
RtlCopyMemory(mapped_view_ptr, msg_ptr, byte_len)
# Python vriant
shmem = mmap.mmap(0, 256, "MyFileMappingObject_ctypes", mmap.ACCESS_WRITE)
shmem.write(b"Message Python process")
print("Hit a key to clean all memory maps and exit...")
msvcrt.getch()
UnmapViewOfFile(mapped_view_ptr)
CloseHandle(mapping_handle)
shmem.close()
if __name__ == "__main__":
print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(item.strip() for item in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform))
main(*sys.argv[1:])
print("\nDone.")
备注:
为函数添加了 argtypes 和 restype。详情可见“指定所需参数类型(函数原型)”和“Return类型”部分,以及课程 MS.Docs for function declarations. This is Undefined Behavior (UB) especially on 64bit:
memcpy 的 2nd 参数是一个 Python 字符串,它 not 与它的 char * 地址相同(更不用说在Python 3,字符串是 wchar_t 基础的)memcpy 期望的,这可能还会产生 UB
常数:
FILE_MAP_ALL_ACCESS的值是0x000F001F(从[=49=打印出来的值]VStudio 2015), 0x04对应FILE_MAP_READ
将 INVALID_HANDLE_VALUE 的旧值转换为 HANDLE 时出错,将其更改为 -1 (如 handleapi.h)
您正在使用 c_wchar_p 调用 CreateFileMappingA。这将为映射对象设置一个仅包含提供的字符串中的第 1st 个字符的名称,因为每个 wchar_t 包含 2 bytes: 0x00 加上相应的 char 值 - 'A' 将表示为 0x00 0x41(通常这是 not true - 特别是 0x00 部分,但在我们的例子中,它是) - 所以lpName 参数中的 2nd char (由于 little-endianness) 将是 0x00 (NUL)
根据上面的页面:
Accessing the standard C library through
cdll.msvcrt
will use an outdated version of the library that may be incompatible with the one being used by Python.因此,我还添加了 [MS.Docs]: RtlCopyMemory function to replace memcpy (you can comment out its line, I left it there just to show that it works), as in the example ([MS.Docs]: Creating Named Shared Memory),您从中获取了代码,并尝试对其进行转换 ([minwinbase.h: #36]:
#define CopyMemory RtlCopyMemory
)已将命名约定更改为 Python 兼容 ([Python]: PEP 8 -- Style Guide for Python Code)
其他(非关键)更改(输出格式、移动代码行以获得更好的结构等等...)
输出:
[cfati@CFATI-5510-0:e:\Work\Dev\Whosebug\q048788549]> "e:\Work\Dev\VEnvs\py_pc064_03.07.06_test0\Scripts\python.exe" code00.py Python 3.7.6 (tags/v3.7.6:43364a7ae0, Dec 19 2019, 00:42:30) [MSC v.1916 64 bit (AMD64)] 64bit on win32 Mapping object handle: 0x000000000000022C Mapped view addr: 0x00000192912B0000 Message length: 35 chars (70 bytes) Hit a key to clean all memory maps and exit... Done.