python查看对象内存地址的函数

Python015

python查看对象内存地址的函数,第1张

在python中可以用id()函数获取对象的内存地址

#例如:

object = 1 + 2

print(id(object)) #4304947776

字符串驻留机制在许多面向对象编程语言中都支持,比如Java、python、Ruby、PHP等,它是一种数据缓存机制,对不可变数据类型使用同一个内存地址,有效的节省了空间,本文主要介绍Python的内存驻留机制。

字符串驻留就是每个字符串只有一个副本,多个对象共享该副本,驻留只针对不可变数据类型,比如字符串,布尔值,数字等。在这些固定数据类型处理中,使用驻留可以有效节省时间和空间,当然在驻留池中创建或者插入新的内容会消耗一定的时间。

下面举例介绍python中的驻留机制。

在Python对象及内存管理机制一文中介绍了python的参数传递以及以及内存管理机制,来看下面一段代码:

知道结果是什么吗?下面是执行结果:

l1和l2内容相同,却指向了不同的内存地址,l2和l3之间使用等号赋值,所以指向了同一个对象。因为列表是可变对象,每创建一个列表,都会重新分配内存,列表对象是没有“内存驻留”机制的。下面来看不可变数据类型的驻留机制。

Jupyter或者控制台交互环境 中执行下面代码:

执行结果:

可以发现a1和b1指向了不同的地址,a2和b2指向了相同的地址,这是为什么呢?

因为启动时,Python 将一个 -5~256 之间整数列表预加载(缓存)到内存中,我们在这个范围内创建一个整数对象时,python会自动引用缓存的对象,不会创建新的整数对象。

浮点型不支持:

如果上面的代码在非交互环境,也就是将代码作为python脚本运行的结果是什么呢?(运行环境为python3.7)

全为True,没有明确的限定临界值,都进行了驻留操作。这是因为使用不同的环境时,代码的优化方式不同。

Jupyter或者控制台交互环境 中:

满足标识符命名规范的字符:

结果:

乘法获取字符串(运行环境为python3.7)

结果:

在非交互环境中:

注意: 字符串是在编译时进行驻留 ,也就是说,如果字符串的值不能在编译时进行计算,将不会驻留。比如下面的例子:

在交互环境执行结果如下:

都指向不同的内存。

python 3.7 非交互环境执行结果:

发现d和e指向不同的内存,因为d和e不是在编译时计算的,而是在运行时计算的。前面的 a = 'aa'*50 是在编译时计算的。

除了上面介绍的python默认的驻留外,可以使用sys模块中的intern()函数来指定驻留内容

结果:

使用intern()后,都指向了相同的地址。

本文主要介绍了python的内存驻留,内存驻留是python优化的一种策略,注意不同运行环境下优化策略不一样,不同的python版本也不相同。注意字符串是在编译时进行驻留。

--THE END--

使用ctypes模块调用WriteProcessMemory函数,在创建程序进程后,就可以修改该程序指定内存地址。WriteProcessMemory的函数原型如下所示。

BOOL WriteProcessMemory(

HANDLE     hProcess,

LPVOID     lpBaseAddress,

LPCVOID    lpBuffer,

SIZE_T     nSize,

SIZE_T*    lpNumberOfBytesWritten

)

其参数含义如下。

·     hProcess:要写内存的进程句柄。

·     lpBaseAddress:要写的内存起始地址。

·     lpBuffer:写入值的地址。

·     nSize:写入值的大小。

·     lpNumberOfBytesWritten   :实际写入的大小。

python代码示例如下:

from ctypes import *

# 定义_PROCESS_INFORMATION结构体

   class _PROCESS_INFORMATION(Structure):     

       _fields_ = [('hProcess', c_void_p),

                     ('hThread', c_void_p),

                     ('dwProcessId', c_ulong),

                     ('dwThreadId', c_ulong)]

   # 定义_STARTUPINFO结构体

   class _STARTUPINFO(Structure):

       _fields_ = [('cb',c_ulong),

                     ('lpReserved', c_char_p),

                     ('lpDesktop', c_char_p),

                     ('lpTitle', c_char_p),

                     ('dwX', c_ulong),

                     ('dwY', c_ulong),

                     ('dwXSize', c_ulong),

                     ('dwYSize', c_ulong),

                     ('dwXCountChars', c_ulong),

                     ('dwYCountChars', c_ulong),

                     ('dwFillAttribute', c_ulong),

                     ('dwFlags', c_ulong),

                     ('wShowWindow', c_ushort),

                     ('cbReserved2', c_ushort),

                     ('lpReserved2', c_char_p),

                     ('hStdInput', c_ulong),

                     ('hStdOutput', c_ulong),

                     ('hStdError', c_ulong)]

   NORMAL_PRIORITY_CLASS = 0x00000020              # 定义NORMAL_PRIORITY_CLASS

   kernel32 = windll.LoadLibrary("kernel32.dll")       # 加载kernel32.dll

   CreateProcess = kernel32.CreateProcessA         # 获得CreateProcess函数地址

   ReadProcessMemory = kernel32.ReadProcessMemory # 获得ReadProcessMemory函数地址

   WriteProcessMemory = kernel32.WriteProcessMemory    # 获得WriteProcessMemory函数地址

   TerminateProcess = kernel32.TerminateProcess

   # 声明结构体

   ProcessInfo = _PROCESS_INFORMATION()

   StartupInfo = _STARTUPINFO()

   file = 'ModifyMe.exe'                           # 要进行修改的文件

   address = 0x0040103c                                # 要修改的内存地址

   buffer = c_char_p("_")                          # 缓冲区地址

   bytesRead = c_ulong(0)                          # 读入的字节数

   bufferSize = len(buffer.value)                  # 缓冲区大小

   # 创建进程

   if CreateProcess(file, 0, 0, 0, 0, NORMAL_PRIORITY_CLASS, 0, 0, byref(StartupInfo), byref(ProcessInfo)):

       # 读取要修改的内存地址,以判断是否是要修改的文件

       if ReadProcessMemory(ProcessInfo.hProcess, address, buffer, bufferSize, byref(bytesRead)):

           if buffer.value == '\x74':

               buffer.value = '\x75'                  # 修改缓冲区内的值,将其写入内存

               # 修改内存

               if WriteProcessMemory(ProcessInfo.hProcess, address, buffer, bufferSize, byref(bytesRead)):

                   print '成功改写内存!'

               else:

                   print '写内存错误!'

           else:

               print '打开了错误的文件!'

              TerminateProcess(ProcessInfo.hProcess,0)   # 如果不是要修改的文件,则终止进程

       else:

           print '读内存错误!'

   else:

       print '不能创建进程!'