ctypes create_string_buffer读取到None后无法继续读取的问题求助
问题分析与彻底修复方案
问题现象
当某次内存读取返回None后,后续所有读取操作都会持续返回空结果,必须关闭并重新启动进程连接才能恢复正常,问题根源出在readString函数的实现上。
原问题代码
def readString(lp_base_address, length): try: read_buffer = ctypes.create_string_buffer(length) lp_number_of_bytes_read = ctypes.c_ulong(0) ctypes.windll.kernel32.ReadProcessMemory(self.handle, lp_base_address, read_buffer, length, lp_number_of_bytes_read) bufferArray = bytearray(read_buffer) found_terminator = bufferArray.find(b'\x00') if found_terminator != -1: return bufferArray[:found_terminator].decode('utf-8') print("[ReadMemory/Error]: terminator not found.\naddress: %s" % hex(lp_base_address)) return "ERROR" except (BufferError, ValueError, TypeError) as error: if self.handle: self.close() self.error_code = self.get_last_error() error = {'msg': str(error), 'Handle': self.handle, 'PID': self.pid, 'Name': self.name, 'ErrorCode': self.error_code} ReadWriteMemoryError(error) for pointer in listOfManyPointers(): result = readString(pointer, 50)
当前临时修复代码
for pointer in listOfManyPointers(): result = readString(pointer, 50) if result == None: # TODO fix and remove this block process.close() connectToProcess()
问题根源
- 未校验
ReadProcessMemory调用结果:该API读取失败时(比如目标地址无效、进程权限不足),不会触发现有捕获的异常,但会导致read_buffer为无效数据,后续逻辑可能隐式返回None,且无效的进程句柄会被保留,导致后续所有读取都失败。 - 参数传递错误:
lp_number_of_bytes_read需要通过ctypes.byref传递指针,原代码直接传值无法正确获取实际读取的字节数。 - 异常捕获范围不全:Windows API调用可能抛出
ctypes.WinError类型的异常,原代码未捕获,会导致程序意外终止或句柄未被清理。 - 返回值不明确:当
ReadProcessMemory失败且未触发异常时,函数没有明确返回值,会隐式返回None,这就是问题中出现None的直接原因。
彻底修复后的代码
def readString(lp_base_address, length): try: read_buffer = ctypes.create_string_buffer(length) lp_number_of_bytes_read = ctypes.c_ulong(0) # 校验API调用是否成功,同时修正参数传递方式 success = ctypes.windll.kernel32.ReadProcessMemory( self.handle, lp_base_address, read_buffer, length, ctypes.byref(lp_number_of_bytes_read) ) if not success: self.error_code = ctypes.windll.kernel32.GetLastError() print(f"[ReadMemory/Error] 读取内存失败,地址: {hex(lp_base_address)},错误码: {self.error_code}") # 读取失败立即关闭无效句柄 if self.handle: self.close() return None bufferArray = bytearray(read_buffer) found_terminator = bufferArray.find(b'\x00') if found_terminator != -1: return bufferArray[:found_terminator].decode('utf-8') print(f"[ReadMemory/Error]: 未找到终止符,地址: {hex(lp_base_address)}") return "ERROR" except (BufferError, ValueError, TypeError, ctypes.WinError) as error: if self.handle: self.close() self.error_code = ctypes.windll.kernel32.GetLastError() error_info = { 'msg': str(error), 'Handle': self.handle, 'PID': self.pid, 'Name': self.name, 'ErrorCode': self.error_code } ReadWriteMemoryError(error_info) return None # 明确返回值,避免隐式返回None
修复说明
- 每次调用
ReadProcessMemory后立即校验结果,失败时直接关闭无效句柄并返回明确的None,避免后续使用失效句柄。 - 修正
lp_number_of_bytes_read的传递方式,确保能正确获取实际读取的字节数。 - 扩展异常捕获范围,覆盖Windows API可能抛出的异常类型。
- 确保函数所有分支都有明确返回值,消除隐式返回
None的情况。
修复后即可移除循环中的临时重启逻辑,读取失败时会自动清理无效句柄,重新连接进程后就能正常执行后续读取操作。
内容的提问来源于stack exchange,提问作者emilector
相关产品推荐
相关产品推荐

