IT狗工作室

第1篇:CPython的内存管理:栈、堆和引用

2020-06-03  本文已影响0人  铁甲万能狗

我们知道在Python编程中,即便较为权威《Python编程指南》一书,也并没有要求Python读者去掌握系统性地理解CPython内部实现中的内存分配以及内存回收等知识。甚至泛滥于网络上的Python编程技术文章很少系统完整性地谈及Python的内存管理。但是知道CPython的内存管理原理,有助于我们编写更高效的代码,有助于我们对较慢的Python代码进行故障排除。

Python的实现版本有很多,例如Jython底层就是JVM,IronPython的底层是.Net,它们的内存管理千差万别取决于底层的运行时系统。我这里说的CPython实现,当然读者若有C/C++的基础,理解CPython的内存管理机制有莫大的帮助。

在掌握CPython如何管理Python对象并将齐存储到内存中,我假定你对堆和栈有一个基本的了解。在CPython实现中,堆和栈有各自的职责


从上面对smt='Hello Word'这些简单的Python赋值语句,你不能单纯地认为将‘Hello World’赋值给变量smt,这是大错特错的,由上面的CPython的简易内存模型可知。,赋值符号右边的是Python对象实体(从C实现的理解,就是构成该PyObject对象所有属性值,这些值有具体的字面量值表示),并且CPython会为该Python对象在堆中分配内存并且存储它。而变量smt仅持有该Python对象实体的引用(从C实现的理解,就是该PyObject对象的内存地址),而不是实际的Python对象.

如果你对C/C++的指针有所理解的话,应该头脑清晰的,其实上面说那么多就是要导出一个概念,什么是Python对象的引用。再来看一个示例。

我们s1变量持有Python对象‘Hello’的引用,对于CPython虚拟机来说,就是在执行s1='Hello Word',将它的内存地址0x71334推入数据栈,那么当CPython碰到同样的语句s2='Hello Word',明显是指向同一个Python对象,那么变量s2和s1一样,它自然持有是‘Hello Word’的引用,即s2实质上拥有的‘Hello Word’的堆中的地址。


ss8.png

对于其他简易的数据类型,也是如出一辙的。那么现在给Python引用我们可以下一个定义。

Python对象的引用:就是Python变量持有Python对象在堆内存中的内存地址。我们可以通过python的内置id函数来正式我们刚才的分析


或者可以使用关键字is 来判断两个变量是否对同一个对象的引用。

在Python中有两种类型的对象,就是可变对象和不可变对象。
可变对象:这个很好例子,比较典型的就是list,一个列表作为一个对象存储在堆内存中,如果我们要更改该列表的某些元素,它将仍然是内存中的同一个列表对象。我们来看看下面一段非常无聊的Python代码

我们在修改列表L中,我们通过列表表达式打印出列表每个对象元素的内存地址,以及列表对象L本身的内存地址,然后在修改列表元素后,再次打印列表对象中的各个对象元素的内存地址,以及L本身的内存地址。

这段代码告诉我们CPython在内存中有如下事实

题外话:整数类型不是右值吗?为什么能返回内存地址?
在Python中,一切事物都是对象,不论是整数,字符串,甚至是其他容器级别的数据类型,都由CPython的C底层由一个叫struct PyObject结构体所封装。PyObject的结构体在CPython运行时存储在堆内中,对于C底层来说,任意的PyObject结构体能够返回内存地址因此是一个左值,但对于Python语义来说,不存在静态语言中的左值和右值,它只能理解的是PyObject这个C实现的对象。

小结

我们理解了CPython的基本的内存模型后,但要说的是,这是一个简化的内存模型,CPython虚拟机对于堆内存管理有一套较为复杂的内存池管理方案。我们后面章节会逐一谈到。目前,我们至少知道了两个基本的概念

我们从堆内存的角度理解为什么CPython要堆Python对象分类可变对象不可变对象,初衷是尽可能低简化堆内存的分配,因为Python变量持有Python对象的引用(或者从C底层去理解,持有PyObject对象的指针)去访问Python对象实体本身,比持有一个Python对象实体的副本更高效,更节省堆和栈的内存开销。

那么当多个Python变量引用同一个Python对象就涉及到概念就引用计数器,引用计数器属于内存垃圾回收的范畴,由引用计数又会牵涉到CPython一个致命的诟病,GIL:全局解释器锁,为什么多年来CPython不能去掉GIL,很大原因跟引用计数器有关。我们后面文章会谈到这些。

上一篇下一篇

猜你喜欢

热点阅读