From 30c9f3991cfb6a8179ea5dcf15fe17030dfbad05 Mon Sep 17 00:00:00 2001 From: Jeremy Hylton Date: Tue, 13 Mar 2001 01:58:22 +0000 Subject: Variety of small INC/DECREF patches that fix reported memory leaks with free variables. Thanks to Martin v. Loewis for finding two of the problems. This fixes SF buf 405583. There is also a C API change: PyFrame_New() is reverting to its pre-2.1 signature. The change introduced by nested scopes was a mistake. XXX Is this okay between beta releases? cell_clear(), the GC helper, must decref its reference to break cycles. frame_dealloc() must dealloc all cell vars and free vars in addition to locals. eval_code2() setup code must INCREF cells it copies out of the closure. The STORE_DEREF opcode implementation must DECREF the object it passes to PyCell_Set(). --- Include/frameobject.h | 3 +-- Modules/pyexpat.c | 3 --- Objects/cellobject.c | 1 + Objects/frameobject.c | 7 ++++--- Python/ceval.c | 11 +++++++---- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/Include/frameobject.h b/Include/frameobject.h index d1a310a..10d4935 100644 --- a/Include/frameobject.h +++ b/Include/frameobject.h @@ -46,8 +46,7 @@ extern DL_IMPORT(PyTypeObject) PyFrame_Type; #define PyFrame_Check(op) ((op)->ob_type == &PyFrame_Type) DL_IMPORT(PyFrameObject *) PyFrame_New(PyThreadState *, PyCodeObject *, - PyObject *, PyObject *, - PyObject *); + PyObject *, PyObject *); /* The rest of the interface is specific for frame objects */ diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c index 4d7008d..ab5ca18 100644 --- a/Modules/pyexpat.c +++ b/Modules/pyexpat.c @@ -356,9 +356,6 @@ call_with_frame(PyCodeObject *c, PyObject* func, PyObject* args) c, /*code*/ tstate->frame->f_globals, /*globals*/ NULL /*locals*/ -#if PYTHON_API_VERSION >= 1010 - ,NULL /*closure*/ -#endif ); if (f == NULL) return NULL; diff --git a/Objects/cellobject.c b/Objects/cellobject.c index d9ecfd7..66fc8d1 100644 --- a/Objects/cellobject.c +++ b/Objects/cellobject.c @@ -83,6 +83,7 @@ cell_traverse(PyCellObject *op, visitproc visit, void *arg) static int cell_clear(PyCellObject *op) { + Py_XDECREF(op->ob_ref); op->ob_ref = NULL; return 0; } diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 18fb0b0..a5300d1 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -65,13 +65,14 @@ static PyFrameObject *free_list = NULL; static void frame_dealloc(PyFrameObject *f) { - int i; + int i, slots; PyObject **fastlocals; Py_TRASHCAN_SAFE_BEGIN(f) /* Kill all local variables */ + slots = f->f_nlocals + f->f_ncells + f->f_nfreevars; fastlocals = f->f_localsplus; - for (i = f->f_nlocals; --i >= 0; ++fastlocals) { + for (i = slots; --i >= 0; ++fastlocals) { Py_XDECREF(*fastlocals); } @@ -108,7 +109,7 @@ PyTypeObject PyFrame_Type = { PyFrameObject * PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals, - PyObject *locals, PyObject *closure) + PyObject *locals) { PyFrameObject *back = tstate->frame; static PyObject *builtin_object; diff --git a/Python/ceval.c b/Python/ceval.c index 8f449a1..cb5936d 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -430,7 +430,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, f = PyFrame_New(tstate, /*back*/ co, /*code*/ - globals, locals, closure); + globals, locals); if (f == NULL) return NULL; @@ -578,8 +578,11 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, } if (f->f_nfreevars) { int i; - for (i = 0; i < f->f_nfreevars; ++i) - freevars[f->f_ncells + i] = PyTuple_GET_ITEM(closure, i); + for (i = 0; i < f->f_nfreevars; ++i) { + PyObject *o = PyTuple_GET_ITEM(closure, i); + Py_INCREF(o); + freevars[f->f_ncells + i] = o; + } } if (tstate->sys_tracefunc != NULL) { @@ -1662,7 +1665,6 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, err = -1; break; } - Py_INCREF(w); PUSH(w); break; @@ -1670,6 +1672,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, w = POP(); x = freevars[oparg]; PyCell_Set(x, w); + Py_DECREF(w); continue; case BUILD_TUPLE: -- cgit v0.12