8.1.2 PyFrameObject 中的动态内存空间
在PyFrameObject 对象所维护的运行时栈中,存储的都是PyObject*,可以看出,这个栈的起始位置是从f_localsplus 开始的。其实不完全正确,f_localsplus 确实维护了一段变动长度的内存,但是这段内存不只是给栈使用的,还有别的对象也会使用:
[frameobject.c](有删节) PyFrameObject * PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals, PyObject *locals) { PyFrameObject *f; Py_ssize_t extras, ncells, nfrees, i; ncells = PyTuple_GET_SIZE(code->co_cellvars); nfrees = PyTuple_GET_SIZE(code->co_freevars); //四部分构成了PyFrameObject 维护的动态内存区, 其大小由extras 确定 extras = code->co_stacksize + code-> co_nlocals + ncells + nfrees; f = PyObject_GC_NewVar(PyFrameObject, &PyFrame_Type, extras); //计算初始化时运行时栈的栈顶 extras = code->co_nlocals + ncells + nfrees; //f_valuestack 维护运行时栈的栈底,f_stacktop 维护运行时栈的栈顶 f->f_valuestack = f->f_localsplus + extras; f->f_stacktop = f->f_valuestack; return f; } |
可见,在创建PyFrameObject 对象时,额外申请的那部分内存中有一部分是给PyCode-Object 对象中存储的那些局部变量的、co_freevars、co_cellvars 使用的(关于co_freevars、co_cellvars,它们涉及Python 中对闭包的实现,在以后考察函数机制时会深入剖析),而另一部分才是给运行时栈使用的。所以,PyFrameObject 对象中的栈的起始位置(也就是栈底)是由f_valuestack 维护的,而f_stacktop 维护了当前的栈顶。图8-3 是一个刚被创建的PyFrameObject 对象的示意图。从中可以清晰地看到运行时栈和PyFrameObject 对象中动态内存部分的关系。
|
| (点击查看大图)图8-3 新创建的PyFrameObject 对象 |
【责任编辑:
夏书 TEL:(010)68476606】